2011-12-16 10 views
1

OpenMP並列処理を使用する関数を記述したいが、並列領域内から呼び出されるかどうかにかかわらず動作するはずである。だから私は、並列処理を抑制するためにif句を使用しますが、私は思ったので、これは動作しません:ms入れ子にされた並列領域を避ける

running func() serial: 
m=1 s=1 
running func() parallel: 
m=16 s=16 

はこのようにfunc()への最初の呼び出しがうまく働いた出力を作成します

#include <omp.h> 
#include <stdio.h> 

int m=0,s=0; 

void func() 
{ 
    bool p = omp_in_parallel(); 
    // if clause to suppress nested parallelism 
#pragma omp parallel if(!p) 
    { 
    /* do some massive work in parallel */ 
#pragma omp master 
    ++m; 
#pragma omp single 
    ++s; 
    } 
} 

int main() 
{ 
    fprintf(stderr,"running func() serial:\n"); 
    m=s=0; 
    func(); 
    fprintf(stderr," m=%d s=%d\n",m,s); 

    fprintf(stderr,"running func() parallel:\n"); 
    m=s=0; 
#pragma omp parallel 
    func(); 
    fprintf(stderr," m=%d s=%d\n",m,s); 
} 

値1を取得する必要がありますが、パラレル領域内からのfunc()への2回目の呼び出しでは、これが抑制されていてもネストされた並列性(1スレッドごとに16チーム)が作成されました。つまり、omp masteromp singleディレクティブは、外側の並列領域ではなく、先行するomp parallel if(!p)ディレクティブにバインドされます。 (コードを繰り返すことなくして)、それは、単一の関数内でこれを行うことは可能です等を定義することがもちろん

は、1次のコード

void work() 
{ 
    /* do some massive work in parallel */ 
#pragma omp master 
    ++m; 
#pragma omp single 
    ++s; 
} 

void func() 
{ 
    if(omp_in_parallel()) 
    work(); 
    else 
#pragma omp parallel 
    work(); 
} 

ことで、この問題を修正することができますが、これは、追加の機能が必要?

答えて

2

OpenMP構造体は、アクティブでない場合でも、常に最も内側の構造体にバインドされます。だから、両方のコードパスのために#pragma omp parallelを保持しているとは考えられません(少なくとも、問題に関する提供された情報があれば)。

これは、そうでなければ条件文を使用すると、非常に問題の多い(バグの読み込み)コードに簡単につながる可能性があるため、このように動作するとよいと思います。次の例を見てください:

void func(void* data, int size) 
{ 
    #pragma omp parallel if(size > 1024) 
    { 
     //do some work 
     #pragma omp barrier 
     //do some more work 
    } 
} 

... 
#pragma omp parallel 
{ 
    //create foo, bar, bar varies massively between different threads (so sometimes bigger, sometimes smaller then 1024 
    func(foo, bar); 
    //do more work 
} 

一般にプログラマは、呼び出される関数の実装の詳細を知っているだけでその動作を必要はありません。したがって、funcがネストされたparallelセクションを作成するかどうか、および正確な条件の下でそれを作成するかどうかを気にする必要はありません。しかし、barrierが外側のparallelにバインドすると、内側が非アクティブな場合、このコードはバグになります。外側のparallelセクションの一部のスレッドがbarrierに遭遇し、いくつかのスレッドでは発生しないためです。したがって、たとえそれがアクティブでなくても、そのような詳細は最奥のparallelの内部に隠れたままです。

個人的に私はそれが違った振る舞いをするような状況に遭遇したことはありませんでした。これは情報の隠蔽などに逆らって行動したかったので、より良い回答を得るために何を達成しようとしているのか少し教えてください。

0

私はopenMP標準を見ました。 句は、実際には幾分誤解を招きやすいように作られています。なぜなら、#pragma omp parallel命令は条件付きではないからです(私が思っていたように)。代わりに、if句はスレッドの数を1に制限し、並列化を抑制することがあります。

ただし、これはグローバル共有変数のスレッドごとの1回の書き込みには使用できません。つまり、omp singleまたはomp masterは使用できません。

+0

はい、それは暗黙のうちに外部レベルでの並列処理がないことを一般的に保証することはできないので、それを暗に意味します。スレッドセーフな共有変数へのアクセスは、ミューテックス(ompのロック)のためのものです。とにかく、do_funcを呼び出す複数のスレッドがある場合、これらのスレッドの1つ(したがって呼び出し)だけをグローバル変数に書きたいと思っていますか?わかりませんあなたの特定のシナリオですが、それは非常に役に立つとは言えません。 – Grizzly

関連する問題