29

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

スレッドは1つだけです。

このコードを正しくコンパイルする方法は誰でも教えてくれます。前もって感謝します。

4

2 に答える 2

38

OpenMP はコード変換プラグマのセットです。つまり、コンパイル時にのみ適用されます。コード変換を既にコンパイル済みのオブジェクト コードに適用することはできません (可能ですが、プロセスがはるかに複雑であり、最近のほとんどのコンパイラが行うことの範囲外です)。-fopenmpリンク フェーズでは、コンパイラが OpenMP ランタイム ライブラリを自動的にリンクするだけで済みますlibgomp。オブジェクト コードに対しては、他には何もしません。

余談ですが、技術的には正しいですが、あなたのコードは OpenMP とはまったく異なる方法で OpenMP を実行しています。まず、OpenMPsectionsコンストラクトを再実装しました。関数内の並列領域は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このコードを 3 つ以上の OpenMP スレッドで実行している場合は、GCC でバグが発生しています。これは次のリリースで修正される予定です)

2 番目に、OpenMPtaskコンストラクトを確認することをお勧めします。これを使用すると、アイドル状態のスレッドによってタスクとして同時に実行されるコードの断片をキューに入れることができます。残念ながら、OpenMP 3.0 をサポートするコンパイラが必要です。これは、MSVC++ を方程式から除外しますが、Windows への移植性を気にする場合に限ります (POSIX スレッドを使用しているため、明らかに気にしません)。

于 2012-08-17T10:45:06.123 に答える
29

OpenMP プラグマは、でコンパイルされた場合にのみ有効になります-fopenmp。それ以外の場合、それらはコンパイラによって完全に無視されます。(したがって、1スレッドのみ...)

-fopenmpしたがって、 OpenMP を使用するすべてのモジュールのコンパイルに追加する必要があります。(最後のリンク手順とは対照的に。)

g++ -c test.cpp -o test.o -fopenmp
g++ test.o -o test -fopenmp -lpthread
于 2012-08-17T08:37:41.507 に答える