ナビゲーション:前へ 上へ 次へ
ナビゲーション:前へ 上へ 次へ
13 barrier指示文
前述のとおり、parallel指示構文、do指示構文、sections指示構文、 parallel do指示構文、parallel sections指示構文、 single指示構文(及び本テキストでは説明しないworkshare指示構文)ではその出口で(nowaitを指定した場合以外)暗黙の同期が取られます。 (注意:これらの指示構文の入口では同期は取られません)barrier指示文は明示的に同期を行いたい場合(バリアー)に利用可能です。 バリアーにおいては他のすべてのスレッドがバリアーまでの処理を完了するまで待ち、その後に実行が継続されます。
以下に4スレッドの場合の参考図を示します。
barrier指示文は以下の書式を持ちます。
!$omp barrier
以下にbarrier指示文を用いた例を示します。 barrier地点で配列aの各成分の値が各スレッドのスレッド番号により更新されることになり、 よって平均値は1.5となるはずです。
program exampleBarrier use omp_lib implicit none integer id real a(4), b(4), avg a = 0 b = (/3, 2, 5, 1/) !$omp parallel num_threads(4) private(id) id = omp_get_thread_num() a(id+1) = id !$omp barrier !$omp single avg = sum(a)/4 print *, "Average =", avg !$omp end single b(id+1) = b(id+1) - avg !$omp end parallel print *, b end program [実行出力例] Average = 1.5000000 1.5000000 0.5000000 3.5000000 -0.5000000仮に!$omp barrierの行を削除して実行すると 配列aのすべての成分の更新が終わる前に avg = sum(a)/4 の計算が行われてしまう可能性があり、正しい結果が得られなくなってしまいます。
[barrier無しの場合の(正しくない)出力例] Average = 0.2500000 2.7500000 1.7500000 4.7500000 0.7500000
13.1 ☆演習課題:barrier指示文
下記に示すプログラムは2つのスレッドで処理を分担しています。しかしながらこのままでは(必ずしも)正しく動きません。 このコードにbarrier指示文を追加して正しく動くように書き換えて下さい。[課題のコード] program kadaiBarrier use omp_lib implicit none integer a(5), b(5), c(10), max_a, max_b, i a = (/10,15,7,3,22/) b = (/20,17,1,30,1/) max_a = 0 max_b = 0 !$omp parallel num_threads(2) if ( omp_get_thread_num() == 0 ) then max_a = maxVal(a) else max_b = maxVal(b) end if !$omp do do i=1,10 c(i) = (max_a+max_b)*i end do !$omp end do !$omp end parallel print *, "maxA + maxB =", max_a+max_b print *, "C has :", c end program
[正しい実行結果の例] maxA + maxB = 52 C has : 52 104 156 208 260 312 364 416 468 520解答例:kadaiBarrier.f90
ナビゲーション:前へ 上へ 次へ