OpenMP 入門

ナビゲーション:前へ   上へ   次へ

13 barrier指示文

前述のとおり、parallel指示構文、do指示構文、sections指示構文、 parallel do指示構文、parallel sections指示構文、 single指示構文(及び本テキストでは説明しないworkshare指示構文)ではその出口で(nowaitを指定した場合以外)暗黙の同期が取られます。 (注意:これらの指示構文の入口では同期は取られません)

barrier指示文は明示的に同期を行いたい場合(バリアー)に利用可能です。 バリアーにおいては他のすべてのスレッドがバリアーまでの処理を完了するまで待ち、その後に実行が継続されます。

以下に4スレッドの場合の参考図を示します。

BarrierDirective

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


ナビゲーション:前へ   上へ   次へ
関連情報
ご案内
© 日本ニューメリカルアルゴリズムズグループ株式会社 2025
Privacy Policy  /  Trademarks