2017-06-20 9 views
0

は、これが私の最初の時間は、OpenMPを使用していると私は、次の実装でコア誤解を感じている:OpenMPの和説明

#include <omp.h> 
#include <stdio.h> 

int main(int argc, char *argv[]) { 

int i, n; 
float a[100], b[100], result; 

/* Some initializations */ 
n = 100; 
result = 0.0; 
for (i=0; i < n; i++) { 
    a[i] = i * 1.0; 
    b[i] = i * 2.0; 
    } 

    //pragma statement for omp here 
    for (int i=0; i < n; i++) 
    result = result + (a[i] * b[i]); 

printf("Final result= %f\n",result); 

} 

プログラムは、加算を伴うドット積を計算するように設計されています。 this questionの回答者は、#pragma omp parallel for reduction(+:results)を使ってforループの並列和を実装するためにリダクションを使用することを提案していますが、私はちょうど#pragma omp parallel forを使用したのと同じ回答を得ます。これは間違っていると書かれた文書は見つけられませんでした。なぜ私が間違っているのかの説明が役に立つでしょう。

+2

あなたのプログラムは間違っているとは限りませんが、それは間違いです。 'result'への更新はすべてのスレッドによって同期なしで行われます。このプログラムは標準的な*データ競争*を持っています。これまで見ていないほど幸運でした(ええ、右)。 'n'を' 10^6'に増やしてみて、何が起こるか見てみましょう。 –

答えて

3

#pragma omp parallel for reduction(+:result)を使用すると正しいです。 #pragma omp parallel forが間違っています。後者は、すべてのスレッドが保護されていない方法でresultに書き込むことを意味します。それはclassical race conditionです。実際には、たとえハードウェアが原子的に動作し、OSが異なるコア上のスレッドをスケジューリングしていないか、まったく純粋な運をスケジューリングしていないなど、偶然に同じ結果が得られる可能性があります。だまされてはいけませんが、コードはまだ間違っています。

残念ながら、正しい結果が得られることを示すだけで、コードが正しいと証明できません。同じ結果を数回出すようにテストすることで、2つのコードが同じであることを示すことはできません。言い換えれば、間違ったコードが必ずしも容易に明らかになるわけではありません。