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つだけです。
誰でもこのコードを正しくコンパイルする方法を教えてくれます。前もって感謝します。
OpenMPはcode transformingプラグマのセットです。つまり、コンパイル時にのみ適用されます。既にコンパイルされたオブジェクトコードにコード変換を適用することはできません(できますが、それははるかにプロセスに関係しており、最近のほとんどのコンパイラが行うことの範囲外です)。コンパイラがOpenMPランタイムライブラリlibgomp
を自動的にリンクするためにのみ、リンクフェーズ中に-fopenmp
が必要です-オブジェクトコードには何もしません。
副次的に、技術的には正しいものの、コードは非常に非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;
}
}
}
(3つ以上のOpenMPスレッドでこのコードを実行中にSIGILL
を取得した場合、GCCのバグが発生し、今後のリリースで修正される予定です)
次に、OpenMP task
コンストラクトを見てみるとよいでしょう。これにより、アイドルスレッドがタスクとして同時に実行するコードの一部をキューに入れることができます。残念ながら、OpenMP 3.0をサポートするコンパイラが必要です。このコンパイラは、方程式からMSVC++を除外しますが、Windowsへの移植性に関心がある場合のみです(POSIXスレッドを使用しているため明らかにそうではありません)。
OpenMPプラグマは、-fopenmp
でコンパイルされた場合にのみ有効になります。それ以外の場合は、コンパイラーによって完全に無視されます。 (したがって、1つのスレッドのみ...)
したがって、OpenMPを使用するすべての単一モジュールのコンパイルに-fopenmp
を追加する必要があります。 (最後のリンク手順とは対照的です。)
g++ -c test.cpp -o test.o -fopenmp
g++ test.o -o test -fopenmp -lpthread