How to compile openmp using g++

2020-02-03 05:37发布

问题:

I have a problem about the openmp compiling.

Like the following code:

#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;
}

Firstly, I compile it using:

g++ test.cpp -fopenmp -lpthread

And, I got the right answer, there are 3 threads totally.

But, when I do the compile like this:

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

there is just only ONE thread.

Anyone can tell me how to compile this code correctly. Thankyou in advance.

回答1:

OpenMP is a set of code transforming pragmas, i.e. they are only applied at compile time. You cannot apply code transformation to an already compiled object code (ok, you can, but it is far more involving process and outside the scope of what most compilers do these days). You need -fopenmp during the link phase only for the compiler to automatically link the OpenMP runtime library libgomp - it does nothing else to the object code.

On a side note, although techically correct, your code does OpenMP in a very non-OpenMP way. First, you have reimplemented the OpenMP sections construct. The parallel region in your main function could be rewritten in a more OpenMP way:

#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;
        }
    }
}

(if you get SIGILL while running this code with more than three OpenMP threads, you have encountered a bug in GCC, that will be fixed in the upcoming release)

Second, you might want to take a look at OpenMP task construct. With it you can queue pieces of code to be executed concurrently as tasks by any idle thread. Unfortunately it requires a compiler which supports OpenMP 3.0, which rules out MSVC++ from the equation, but only if you care about portability to Windows (and you obviously don't, because you are using POSIX threads).



回答2:

The OpenMP pragmas are only enabled when compiled with -fopenmp. Otherwise they are completely ignored by the compiler. (Hence, only 1 thread...)

Therefore, you will need to add -fopenmp to the compilation of every single module that uses OpenMP. (As opposed to just the final linking step.)

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