2017-12-04 7 views
0
#pragma omp parallel for  
for (int i = 0; i <500; i++) 
    for (j=i; j < 102342; j++) 
    { 
     Output[j] += staticConstant[i] * data[j-i]; 
    } 
} 

いくつかのベクトルの答えは同じで、いくつかは異なっています。これの理由は何でしょうか?最初は浮いていると思っていたので、すべてを倍に変えました。同じ5-6の答えがあります。ランダムな値の非常に近い大きなブロックと非常に遠いブロックがあります。並列化したときの答えが異なる

答えて

1

Output[j]に書き込むスレッドが複数あります。競合状態が発生します。あるスレッドによって書き込まれた値は、別の値を持つ別のスレッドに置き換えられます。

1

問題は、あなたの内側のループは、例えば、以下の二つの文が並行して起こる可能性があり、書き込み競合状態を持っているので、ということです:コードは行ごとに沸く何

Output[42] = Output[42] + staticConstant[9] * data[42-9]; 
Output[42] = Output[42] + staticConstant[19] * data[42-19]; 

は次のとおりです。

Load O[42] to R1 
Load C[] to R2 
Add R2 to R1 
Store R1 to O[42] 

しかし、paralleliserは次のように実行しているコードにつながる可能性:

Load O[42] to R1 
Load O[42] to R3 
Load C[9] to R2 
Load C[19] to R4 
Add R2 to R1 
Add R4 to R3 
Store R1 to O[42] 
Store R3 to O[42] 

ご覧のとおり、2つのLoad O[42]行は、C[9]またはC[19]を追加する前に値をロードするので、最初の計算は実質的に無視されます。

最も簡単な修正は次のとおりです。唯一の内側のループが並列化されるよう

for (int i = 0; i <500; i++) 
{ 
#pragma omp parallel for  
    for (j=i; j < 102342; j++) 
    { 
     Output[j] += staticConstant[i] * data[j-i]; 
    } 
} 

は今何の競合状態は存在しません。

+0

ありがとうございます。<3ループでリダクションを使用するにはどうすればよいですか?私はopenmpの古いバージョンを使用しているので、私はそれをオーバーロードできません。 – StephanieLoves

+0

他のオプションは、2つのループを交換することです。 'j'ループはより多くの反復を持つので、最も外側のループを並列化することでオーバーヘッドが少なくなります。 –

関連する問題