Как скомпилировать openmp с помощью g++ - программирование

Как скомпилировать openmp с помощью g++

У меня проблема с компиляцией 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

существует только один поток.

Любой может сказать мне, как правильно скомпилировать этот код. Заранее благодарю.

4b9b3361

Ответ 1

OpenMP - это набор правил преобразования кода, т.е. они применяются только во время компиляции. Вы не можете применить преобразование кода в уже скомпилированный объектный код (хорошо, вы можете, но это гораздо больше связано с процессом и выходит за рамки того, что делают большинство компиляторов в наши дни). Вам нужно -fopenmp во время фазы ссылки только для того, чтобы компилятор автоматически связал библиотеку времени выполнения OpenMP libgomp - он ничего не делает для объектного кода.

На стороне примечания, хотя технически корректно, ваш код делает OpenMP в очень не-OpenMP-способе. Во-первых, вы переопределили конструкцию OpenMP sections. Параллельная область в вашей функции main может быть переписана более открытым способом OpenMP:

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

(если вы получаете SIGILL при запуске этого кода с более чем тремя потоками OpenMP, вы столкнулись с ошибкой в ​​GCC, которая будет исправлена ​​в предстоящем выпуске)

Во-вторых, вы можете взглянуть на конструкцию OpenMP task. С его помощью вы можете ставить в очередь фрагменты кода, которые должны выполняться одновременно как задачи любым простоями. К сожалению, для этого требуется компилятор, который поддерживает OpenMP 3.0, который исключает MSVС++ из уравнения, но только если вы заботитесь о переносимости в Windows (и, очевидно, нет, потому что вы используете потоки POSIX).

Ответ 2

Прагмы OpenMP разрешены только при компиляции с помощью -fopenmp. В противном случае компилятор полностью игнорирует их. (Следовательно, только 1 поток...)

Поэтому вам нужно добавить -fopenmp в компиляцию каждого модуля, использующего OpenMP. (В отличие от всего лишь последнего шага связывания).

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