-1

テスト用に簡単なコードを用意しました。これは、コードの最も重要な部分です。

#pragma omp parallel sections
{
 #pragma omp section 
 {
 for (int j=0;j<100000;j++)
  for (int i=0;i<1000;i++) a1[i]=1;
 }
 #pragma omp section 
 {
 for (int j=0;j<100000;j++)
  for (int i=0;i<1000;i++) a2[i]=1;
 }
}

プログラムを MinGW コンパイラでコンパイルしたところ、期待どおりの結果が得られました。Linux のみのコンピューターを使用するので、Linux でコードをコンパイルしました (同じマシンを使用)。gcc 4.7.2 および intel 12.1.0 コンパイラを使用しました。プログラムの効率が大幅に低下しました。逐次プログラムより遅い ( omp_set_num_threads(1))

スレッドでプライベート配列も試しましたが、効果は似ています。

誰かが説明を提案できますか?

4

1 に答える 1

0

コードで何を達成しようとしているのか正確にはわかりませんが、効率の違いは、使用しているコンパイラがセクション内セクションを持つコードの処理方法を知らないことが原因である可能性があります。

まず、別のコンパイラを試してください。私の経験から、gcc-4.8.0 は OpenMP でうまく動作するので、最初はそれを試すことができます。

次に、最適化フラグを使用してください。パフォーマンスを測定する場合は、-O1 -O2 または -O3 のいずれかを使用するのが適切です。後者を使用すると最高のパフォーマンスが得られますが、浮動小数点演算の精度がわずかに低下する数学関数を使用するショートカットが必要になります。

g++ -fopenmp name.cpp -O3

興味があれば、このページでコンパイラ フラグの詳細を読むことができます。

最後に、OpenMP の経験がどれくらいあるかはわかりませんが、OpenMP でループを処理する場合は通常、次のようにします。

#pragma omp parallel for
for(int i=0; i<N; ++i)
   doSomething();

さらに、ネストされたループを使用している場合は、collapseディレクティブを使用して、ネストされたループを単一のループに変えるようにコンパイラに通知できます (これにより、パフォーマンスが向上する可能性があります)。

#pragma omp parallel for collapse(2) private(i, j)
for(int i=0; i<N; ++i)
   for(int j=0; j<N; ++j)
       doSomething();

ここで読むことができる折りたたみを使用する際に注意すべきことがいくつかあります。私の経験から、これはさらに効率的であることが証明されているため、個人的にはそれらを手動で単一のループに変換することを好みます。

于 2014-01-15T09:23:32.137 に答える