私は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;
}
はい、できます。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
に到達しない場合があります。
あなたの場合、sum = sum + val
は prefix sum 計算である1次元配列ではval[i] = val[i-1] + val[i]
(または2次元配列ではval[rows][cols] = val[rows][cols-1] + val[rows][cols]
)として解釈できます。
簡約は、接頭辞和の解決策の1つです。「+」、「-」、「*」、「/」などの可換連想演算子の簡約を使用できます。