web-dev-qa-db-ja.com

OpenMPによる削減

私はopenmpを使用して2d行列の平均を計算しようとしています。この2Dマトリックスは実際には画像です。

データのスレッドごとの分割を行っています。たとえば、Nスレッドがある場合、Rows/Nの数の行をthread0で処理します。

私の質問は、「#pragma omp parallel」でopenmp削減句を使用できますか?

#pragma omp parallel reduction( + : sum )
{
    if( thread == 0 )
       bla bla code 
       sum = sum + val;

    else if( thread == 1 )
       bla bla code
       sum = sum + val;
}
13
mkuse

はい、できます。reduction句は、並列領域全体と個々のforワークシェアリング構造に適用できます。これにより、たとえば異なる並列セクションで実行される計算の削減(コードを再構築するための推奨される方法):

#pragma omp parallel sections private(val) reduction(+:sum)
{
   #pragma omp section
   {
      bla bla code
      sum += val;
   }
   #pragma omp section
   {
      bla bla code
      sum += val;
   }
}

セクションを使用してループを再実装する代わりに、OpenMP forワークシェアリングコンストラクトを使用して、ループの反復をチーム内のスレッド間で自動的に分散することもできます。

#pragma omp parallel for private(val) reduction(+:sum)
for (row = 0; row < Rows; row++)
{
   bla bla code
   sum += val;
}

リダクション変数はプライベートであり、それらの中間値(つまり、parallel領域の最後でリダクションの前に保持される値)は部分的なものであり、あまり有用ではないことに注意してください。たとえば、次のシリアルループは、(簡単に?)縮小演算を使用してパラレルループに変換できません。

for (row = 0; row < Rows; row++)
{
   bla bla code
   sum += val;
   if (sum > threshold)
      yada yada code
}

ここでyada yada codeは、sumの累積値がthresholdの値を渡したら、反復ごとに実行する必要があります。ループが並列で実行される場合、sumのプライベート値は、合計が到達しても、決してthresholdに到達しない場合があります。

24
Hristo Iliev

あなたの場合、sum = sum + valprefix sum 計算である1次元配列ではval[i] = val[i-1] + val[i](または2次元配列ではval[rows][cols] = val[rows][cols-1] + val[rows][cols])として解釈できます。

簡約は、接頭辞和の解決策の1つです。「+」、「-」、「*」、「/」などの可換連想演算子の簡約を使用できます。

0
Charles Chow