1

私は解決して理解しようとしている非常に奇妙な問題を抱えています。次の形式のネストされた for ループがあります。

#pragma omp parallel for schedule(guided) shared(Array) collapse(3)
for (int i=istart; i<iend; i++)
{
  for (int j=jstart; j<jend; j++)
  {
    for(int k=kstart; k<kend; k++)
    {
       Int IJK = (i*(jend-jstart) + (j-jstart))*(kend-kstart) + (k-kstart);
       Array[3*IJK + 2] = an operation with some shared values;
    }
  }
}

この形式の 3 つのループがあり、それぞれArray[3*IJK]、 、Array[3*IJK + 1]およびがありArray[3*IJK+2]ます。Array も実際には共有ポインターであり、 の値に対してIJK、関数が実際に呼び出されます (インライン化されます)。

最初にすべてのループを並列化してプログラムを実行しようとしましたが、シリアルの結果と比較して結果が異なります。

今、奇妙な部分が来ます。

これと同じ構造の for ループは、Array[3*IJK + 1]並列化されたときに正しい結果を生成します (この場合、他のループはシリアルです)。しかし、他のループの 1 つを並列化するとすぐに、異なる結果が得られます。単独で並列化したときに正しい結果を生成するのは、この単一のループだけです。

また、の代わりにcollapse, またはを使用しないと、異なる結果が得られます。上記のステートメントでのみ、ループで正しい結果が得られます。collapse(2)collapse(3)#pragmaArray[3*IJK + 1]

書き込まれた順序に関係があるのではないかと思いましたArrayが、順序付けられた節と構文を使用すると、まだ間違った結果が得られます。

これの原因は何ですか?

4

1 に答える 1

0

あなたのシリアルケースは正しいですか?

あなたのIJK計算は私には意味がありません。一つには、まったく依存していませんj。現状では、2 つのスレッドが異なる j を持つ同じ (i,k) ペアを取得した場合 (確かに可能です) collapse(3)、両方が同じ IJK に書き込もうとするため、競合状態が発生します。

次のようなものが欲しくありませんか

   Int IJK = (i*(jend-jstart) + (j-jstart))*(kend-kstart) + (k-kstart);

?

于 2012-08-15T20:13:01.757 に答える