2016-12-09 11 views
0

は、私は元のコードがあります。OpenMPの最小値の配列

min = INT_MAX; 
for (i=0;i<N;i++) 
    if (A[i]<min) 
    min = A[i]; 
for (i=0;i<N;i++) 
    A[i]=A[i]-min; 

を、私はこれの並列バージョンを取得したいと私はこれでした:

min = INT_MAX; 
#pragma omp parallel private(i){ 
minl = INT_MAX; 
#pragma omp for 
for (i=0;i<N;i++) 
    if (A[i]<minl) 
    minl=A[i]; 
#pragma omp critical{ 
if (minl<min) 
    min=minl; 
} 
#pragma omp for 
for (i=0;i<N;i++) 
    A[i]=A[i]-min; 
} 

は、並列コードの右か? #pragma omp barrierを#pragma omp criticalの前に書く必要があるのか​​どうか疑問に思っていたので、グローバル最小値を計算する前にすべての最小値が計算されていることを確認してください。

+0

いいえ、正しくはありません。 criticalを使用することもできますが、この目的でOpenMP 4.0には#pragma omp for reduction(min:....)が追加されました。最新の実装を使用する十分な理由がほぼあります。 – tim18

+0

そして、私はそれを減らさずにやりたいのであれば、私は何を変える必要がありますか? – Unknown

+0

内部のsimd削減と外側の並列スレッドの削減を設定するかどうかは不安です(問題が十分に大きい場合は良い方法です)。シングルスレッドsimdの削減はおそらくN <80000程度で十分です。残念ながら、simdの削減のためのompは、すべてのコンパイラで同じように機能しません(Microsoftではまったくそうではありません)。 – tim18

答えて

1

コードは正しいです。 1つのスレッドがクリティカルセクションに入ったときにすべてmin_lを計算する必要がないため、#pragma omp barrierを追加する必要はありません。また、ループ領域の終わりに暗黙のバリアがあります。

さらに、ループ反復変数iを明示的に宣言する必要はありません。

あなたが代わりにminlのあなたの手動マージの削減を使用してコードを向上させることができます。

#pragma omp for reduction(min:min) 
for (i=0;i<N;i++) 
    if (A[i]<min) 
    min=A[i]; 

注:削減のためのminオペレータは、OpenMP 3.1以降で使用可能です。

+0

助けてくれてありがとう! – Unknown

+0

Visual Studio 2017は次のように言っています: '' min ':OpenMPのreduce' clause'のオペレータトークンが無効です。何か案が? – Royi

+0

@Royi afaik Vsは、古典的なバージョンのOpenmp 2.0のみをサポートしています。 – Zulan

関連する問題