ナビゲーション:前へ 上へ 次へ
ナビゲーション:前へ 上へ 次へ
10 reduction指示節
初期値100に1から10000までの数値を足し合わせてその結果を表示する下記のプログラムコードを考えます。program reduction implicit none integer i, total total = 100 do i=1, 10000 total = total + i end do print *, "Total =", total end program [実行結果例] Total = 50005100このプログラムをOpenMPのdo指示構文を用いて並列化することを考えます。 次の(誤った)例のようにdo指示構文をそのまま適用しても正しい結果は得られません。 これは並列領域において変数 total が更新される処理(total = total + iの処理)で競合が生じる場合があり、 必ずしも正しい計算が行われないからです。
[誤った並列化例] program reduction implicit none integer i, total total = 100 !$omp parallel !$omp do do i=1, 10000 total = total + i end do !$omp end do !$omp end parallel print *, "Total =", total end program [実行結果例その1] Total = 50005100 [実行結果例その2] Total = 44376899 [実行結果例その3] Total = 46100065このような場合にreduction指示節が利用可能です。 reduction指示節はparallel指示文、do指示文、section指示文で指定可能で以下の書式を持ちます。
reduction( {演算 | 組込手続} : list)ここで演算は+、*、-、.and.、.or.、.eqv.、.neqv.のいずれかで、 組込手続はmax、min、iand、ior、ieorのいずれかです。
reduction指示節が指定された場合、listで示される変数のprivateコピーがスレッド毎に作成され、下記に示されるように初期化されます。
演算|組込手続 | 初期値 |
+ | 0 |
* | 1 |
- | 0 |
.and. | .true. |
.or. | .false. |
.eqv. | .true. |
.neqv. | .false. |
max | listで示される変数の型で表現可能な最小値 |
max | listで示される変数の型で表現可能な最大値 |
iand | すべてのビットが1 |
ior | 0 |
ieor | 0 |
該当構造化ブロックの最後ではそれぞれのスレッドのprivateコピー及び共有された変数が演算もしくは組込手続が示す方法により集計されて共有された変数に格納されます。
以下にその概念図を示します。
以下にreduction指示節を指定し、正しく total を計算するプログラムコード例を示します。
[reduction指示節を指定する例] program reduction implicit none integer i, total total = 100 !$omp parallel !$omp do reduction(+:total) do i=1, 10000 total = total + i end do !$omp end do !$omp end parallel print *, "Total =", total end program [実行結果例その1] Total = 50005100 [実行結果例その2] Total = 50005100 [実行結果例その3] Total = 50005100
10.1 ☆演習課題:reduction指示節
下記に示すプログラムは1から10までの数値を掛けあわせて出力するプログラムですが、 このプログラムをREDUCTION指示節を利用して並列化して下さい。[課題のコード] program kadaiReduction implicit none integer i, prod prod = 1 do i=1,10 prod = prod * i end do print *, "Product =", prod end program
[実行例] Product = 3628800解答例:kadaiReduction.f90
ナビゲーション:前へ 上へ 次へ