2016-04-11 10 views
3

私は3D配列zを持っています。すべての要素の値は1です。OpenMPの崩壊が間違った結果をもたらす

今、私が行います

#pragma omp parallel for collapse(3) shared(z) 
for (int i=0; i < SIZE; ++i) { 
    for (int j=0; j < SIZE; ++j) { 
     for (int k=0; k < SIZE; ++k) { 
      for (int n=0; n < ITERATIONS-1; ++n) { 
       z[i][j][k] += 1; 
      } 
     } 
    } 
} 

これは、各要素にITERATIONSを追加する必要がありますし、それはありません。 collapse(3)collapse(4)に変更すると(for-loopsが4つあるため)、私は正しい結果を得られません。

4つのループをすべて折りたたむことはできませんか?

+0

少なくとも1つのスレッドがライターである場合、複数のスレッドは同期なしで同じメモリ位置にアクセスできません。 'z [i] [j] [k]'を更新する前に、 '#pragma omp atomic update'を追加しようとするとよいでしょう。とにかく、メモリフェンスとキャッシュ競合のために遅くなるでしょう。 Gillesが示唆しているように、削減を使用するほうがはるかに優れています。 –

+0

含まれている最も内側のループで折り畳まれることはほとんど意味を持ちませんが、 'schedule(static、16)'を追加するとパフォーマンスが向上します。 –

答えて

2

第4ループは、第3ループと同じように並列化できないという問題があります。あなた自身を説得するために、最後のループだけを考えてみてください。それはなる:

int zz = z[i][j][k]; 
for (int n=0; n < ITERATIONS-1; ++n) { 
    zz += 1; 
} 
z[i][j][k] = zz; 

それを並列化するために、あなたは右、reduction(+:zz)ディレクティブを追加する必要があるでしょうか?
あなたのcollapse(4)についてはまあ同じ話です。私はわからないんだけど、そのすべての可能な場合でも、reduction(+:z)を追加すると、いくつかの問題を提起します:

CまたはC++での配列のための reduction句は、以降のOpenMP 4.5でサポートされている、と私は知らない
  1. コンパイラはそれを現時点でサポートしています(私は確信していますが)。
  2. 縮小アスペクトを管理する複雑な仕組みのため、おそらくコードは非常に遅くなるでしょう。

要するに、必要に応じてcollapse(3)以下に固執するか、ループを別々に並列化します。

+1

OpenMP 4.5はC/C++の配列削減をサポートしていますか?私はそれを知らなかった。 –

+2

@Zboson [C/C++配列セクションの削減のセマンティクスが追加され、縮小での配列とポインタの使用に関する制限が削除されました(セクション2.15.3.6、ページ201を参照)](http://www.openmp.org/ mp-documents/openmp-4.5.pdf#section.D.1) – Gilles

+0

@Gillesヘッドアップに感謝します。これは、私がOpenMPが本当に必要と感じていることを実行した主なものの1つです。 – NoseKnowsAll