2016-04-06 11 views
0

いくつかの構造体の行列に直列に適用されるべき関数はほとんどありません。入れ子にされたループを持つOpenMP

for(int t = 0; t < maxT; ++t) 
{ 
    for(int i = 0; i < maxI; ++i) 
     for(int j = 0; j < maxJ; ++j) 
      function1(i, j); 

    for(int i = 0; i < maxI; ++i) 
     for(int j = 0; j < maxJ; ++j) 
      function2(i, j); 
} 

は今、私はそのコードを並列化しようとしている:

#pragma omp parallel 
{ 
    for(int t = 0; t < maxT; ++t) 
    { 
     #pragma omp single 
     function3(); // call this function once (once for each iteration of t) 
     #pragma omp for 
     for(int i = 0; i < sizeI; ++i) 
      for(int j = 0; j < sizeJ; ++j) 
       function1(i, j); 

     #pragma omp for 
     for(int i = 0; i < sizeI; ++i) 
      for(int j = 0; j < sizeJ; ++j) 
       function2(i, j); 
    } 
} 

は、それは正しいですか?シングルスレッドのために私は次のコードを使用しますか スレッドを再利用する方法(メインループで新しいスレッドチームを作成しない)で動作しますか?

更新:明示的なバリアは本当に不要です。

実際、私はこの質問をしたときに混乱していたようです。コード例が正しく動作しています。問題は次のとおりです。#pragma omp parrallelの後にfunction(コード内のコメント行)を1回呼び出すことが可能です(繰り返しごとに各スレッドでfunction3を呼び出さないようにする)。インクリメント演算子やその他の関数を呼び出すには#pragma omp atomicがありますが、任意の関数(または一般的にはコードブロックを実行する)の1つのインスタンスを呼び出す場合はどうしたらいいですか?

Markさんのコメント。私は、並列化された関数でデータ競合を処理することを前提としています。ここでの唯一の質問は、OpenMPを使用する場合、stlコンテナは単にスレッドセーフではありませんか?つまり、複数のスレッドからstd :: listのpush_back()を実行したい場合は、そのリストを手動でロックする必要があります。

更新2:私は、#pragma omp singleを使用する必要があることを、並列セクションで単一アクションを実行することがわかった。だから、この質問は閉じられる。

+1

*正しいですか?*おそらく。おそらくない。あなたの機能は副作用によって機能するようです。それらの副作用はデータ競争を実装するかもしれません... –

答えて

2

はいこれは、すべてのスレッドが外側のループでtを繰り返し、スレッド間でループの反復の作業を分割する1つの並列領域を作成します。

#pragma omp forには暗黙のバリアがありますので、明示的なバリアを記述する必要はありません。この暗黙的な障壁は、nowait節(すなわち、#pragma omp for nowait)を使用して削除できます。

関連する問題