首页 文章

如何使用g编译openmp

提问于
浏览
18

我有一个关于openmp编译的问题 .

如下代码:

#include <iostream> 
#include <pthread.h>
#include <omp.h>
#include <semaphore.h>
#include <stack>
using namespace std;
sem_t empty,full;
stack<int> stk;
void produce(int i)
{
    {
    sem_wait(&empty);
            cout<<"produce "<<i*i<<endl;
            stk.push(i*i);
    sem_post(&full);
    }
}
void consume1(int &x)
{
    sem_wait(&full);
            int data=stk.top();
            stk.pop();
            x=data;
    sem_post(&empty);
}
void consume2()
{
    sem_wait(&full);
            int data=stk.top();
            stk.pop();
            cout<<"consume2 "<<data<<endl;
    sem_post(&empty);
}
int main()
{
    sem_init(&empty,0,1);
    sem_init(&full,0,0);
    pthread_t t1,t2,t3;
    omp_set_num_threads(3);
    int TID=0;
    #pragma omp parallel private(TID)
    {
            TID=omp_get_thread_num();
            if(TID==0)
            {
            cout<<"There are "<<omp_get_num_threads()<<" threads"<<endl;
            for(int i=0;i<5;i++)
                    produce(i);
            }
            else if(TID==1)
            {
                    int x;
                    while(true)
                    {
                            consume1(x);
                            cout<<"consume1 "<<x<<endl;
                    }
            }
            else if(TID==2)
            {
                    int x;
                    while(true)
                    {
                            consume1(x);
                            cout<<"consume2 "<<x<<endl;
                    }
            }
    }
    return 0;
}

首先,我使用以下方法编译它:

g++ test.cpp -fopenmp -lpthread

而且,我得到了正确的答案,共有3个主题 .

但是,当我这样编译时:

g++ -c test.cpp -o test.o
g++ test.o -o test -fopenmp -lpthread

只有一个主题 .

任何人都可以告诉我如何正确编译此代码 . 先感谢您 .

2 回答

  • 26

    OpenMP是一组转换编译指示的代码,即它们仅在编译时应用 . 您不能将代码转换应用于已编译的对象代码(好吧,您可以,但它更多涉及流程,超出了大多数编译器最近所做的范围) . 在链接阶段,您只需要编译器自动链接OpenMP运行时库 libgomp 就需要 -fopenmp - 它对目标代码没有任何其他作用 .

    另外,虽然技术上正确,但您的代码以非OpenMP方式执行OpenMP . 首先,您重新实现了OpenMP sections 构造 . 您可以使用更多OpenMP方式重写 main 函数中的并行区域:

    #pragma omp parallel sections
    {
        #pragma omp section
        {
            cout<<"There are "<<omp_get_num_threads()<<" threads"<<endl;
            for(int i=0;i<5;i++)
                produce(i);
        }
        #pragma omp section
        {
            int x;
            while(true)
            {
                consume1(x);
                cout<<"consume1 "<<x<<endl;
            }
        }
        #pragma omp section
        {
            int x;
            while(true)
            {
                consume1(x);
                cout<<"consume2 "<<x<<endl;
            }
        }
    }
    

    (如果在运行带有三个以上OpenMP线程的代码时得到 SIGILL ,则在GCC中遇到了一个错误,将在即将发布的版本中修复)

    其次,您可能需要查看OpenMP task 构造 . 有了它,您可以将任何空闲线程的代码段同时作为任务排队 . 不幸的是,它需要一个支持OpenMP 3.0的编译器,它可以从等式中排除MSVC,但前提是你关心Windows的可移植性(你很明显没有,因为你使用的是POSIX线程) .

  • 15

    仅当使用 -fopenmp 进行编译时,才会启用OpenMP pragma . 否则编译器会完全忽略它们 . (因此,只有1个线程...)

    因此,您需要将 -fopenmp 添加到使用OpenMP的每个模块的编译中 . (与最后的连接步骤相反 . )

    g++ -c test.cpp -o test.o -fopenmp
    g++ test.o -o test -fopenmp -lpthread
    

相关问题