2012-08-17 8 views
16

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 

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

+3

あなたが '-fopenmp'を持っていなければ、OpenMPのプラグマは無視されると思います。したがって、OpenMPプラグマを持つすべてのモジュールで '-fopenmp'が必要になります。 – Mysticial

+0

@Mysticial .oファイルに.cppをコンパイルするときに-fopenmpを追加する必要があると思いますか? –

+1

うん。 'g ++ -c test.cpp -o test.o -fopenmp'を試してください。それがうまくいくなら私はそれを答えにします。 – Mysticial

答えて

15

OpenMPプラグマは、-fopenmpでコンパイルすると有効になります。それ以外の場合は、コンパイラによって完全に無視されます。したがって、OpenMPを使用するすべてのモジュールのコンパイルに-fopenmpを追加する必要があります。 (単に最終連結工程とは対照的に)

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

のOpenMP、すなわち、それらは唯一のコンパイル時に適用され、プラグマを変換コードのセットです。既にコンパイルされたオブジェクトコードにコード変換を適用することはできませんが(大丈夫ですが、最近のほとんどのコンパイラの処理の範囲外です)。コンパイラが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; 
     } 
    } 
} 

(つ以上のOpenMPのスレッドでこのコードを実行している間、あなたがSIGILLを取得する場合、あなたがなりますGCCのバグに遭遇してきました

第2に、OpenMP taskの構成を見てみるとよいでしょう。これにより、アイドル状態のスレッドがタスクとして同時に実行するコードをキューに入れることができます。残念ながら、OpenMP 3.0をサポートするコンパイラが必要です。これはMSVC++を除外しますが、Windowsへの移植性を気にしている場合に限ります(POSIXスレッドを使用しているため、明らかにそうではありません)。

+3

+1実際にOPのコードをより密接に見る義務を越えた+1。 – Mysticial

関連する問題