2016-06-30 13 views
1

openmpで "reduce"を使用している私のコードは、実行結果と同じ結果を返しません。Openmpでの削減は、コード内の同じスレッド数で異なる結果を返します。

ケース1:使用して "削減"(ⅱ)FUNCと

sum = 0; 
omp_set_num_threads(4); 
#pragma omp parallel for reduction(+:sum) 
for(ii = 0; ii < 100; i++) 
    sum = sum + func(ii); 

は副作用があります。実際、func(ii)は並列実行で競合状態につながる可能性のある他のcalcul()関数を使用します。私はcalcul()関数がこの問題の原因になると思います。しかし、私は「クリティカル」を使用しますが、結果は常に同じですが、このソリューションはパフォーマンスにはあまり適していません。

ケース第2回:使用

func(int val) 
{ 
    read_file(val); 
    calcul(); /*calculate something from reading_file(val)*/ 
    return val_fin; 
} 

はそれを解決するために私を助けてくださいFUNC(ⅱ)機能付き

sum = 0; 
#pragma omp parallel for 
for(ii = 0; ii < 100; i++) 
{ 
    #pragma omp critical 
    sum = sum + func(ii); 
} 

"クリティカル"?

ありがとうございます!

+0

あなたの問題は、 'reduction'一部ではなく、' FUNC(ⅱ) 'コール内の競合状態にないように見えます。 'func'や' calcul'のコードを見ることができないので、もっと言いにくいです。 –

+0

こんにちはダン、私のfunc(ii)も複雑です。私はあなたにそのコピーfunc(ii){... read(ii); ... calcul(); ...戻り値。 } – hamalo

+0

問題を再現できるだけの十分な機能を投稿する必要はありません。 [最小限で完全で検証可能なサンプルの作成方法](http://stackoverflow.com/help/mcve)を参照してください。 –

答えて

0

コード内のすべてが正しい場合でも、操作(追加)の結合性のために、OpenMPの削減とは異なる結果が得られる可能性があります。 与えられたスレッド数に対して同じ結果を再現できるようにするには、共有配列の各スレッドの部分合計を格納して、自分で削減を実装する必要があります。並列領域の後で、マスタースレッドはこれらの結果を追加できます。このアプローチは、スレッドが常に同じ反復、すなわち静的スケジューリング・ポリシーを実行することを意味する。

関連質問: Order of execution in Reduction Operation in OpenMP

+0

ありがとうPhadjido:D – hamalo

1

2番目のケースでパフォーマンスが低下する理由は、ループ本体全体がcriticalであるため、実際には何も並列に実行できません。

あなたには、いくつかの競合状態がcalcul機能であると言うので、ちょうどfunc内部のその行にcriticalセクションを置くことを検討してください。そうすることで、ファイルを並列に読み取ることができます(これは、実行を遅くするI/Oかもしれません)。

パフォーマンスがまだ悪い場合は、ネストされたcalcul関数を調べ、競合条件を特定する必要があります。

基本的には、criticalセクションを可能な限り押し下げるか、まったく削除する必要があります。共有変数を非常に簡単に更新する場合、代わりにOpenMP atomicプラグマを使用することができます。これはパフォーマンスは向上しますが、柔軟性は大幅に低下します。

+0

ありがとう@ダン。私は同じ結果に焦点を当てています。「クリティカル」はこの質問に答えることができますが、パフォーマンスにとってはあまり良くありません。私はあなたのサポートでお試しになります – hamalo

関連する問題