HPCチューニングサービス
HPCチューニング
サービス

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

14 critical指示構文

共有データの更新を行う際に複数のスレッド間で競合が発生し、意図した結果が得られない場合があります。 critical指示構文を使うと他のスレッドと同時に実行されないことが保証される領域(クリティカルセクション等と呼ばれる)を指定することができます。

以下に参考図を示します。

CriticalDirective

理解を深める上でcritical指示構文を用いる次のプログラムコードを考えます。

program exampleCritical
  implicit none
  integer,parameter :: N = 10
  integer myTask, nextTask
  nextTask = 1
!$omp parallel private(mytask)
  do
!$omp critical
    myTask = nextTask
    nextTask = nextTask + 1
!$omp end critical
    if ( myTask > N ) exit
    print *, "Processing task =", myTask
  end do
!$omp end parallel
  print *, "Done..."
end
このコードは各スレッドが用意されている仕事(task)を順番に処理していきますが、 仕事の割り当てを行う以下の部分は他のスレッドと同時に実行されては困る部分ですので、 critical指示構文でそれを防いでいます。
!$omp critical
    myTask = nextTask
    nextTask = nextTask + 1
!$omp end critical
仮にcritical指示構文を使わなかった場合、 myTask = nextTaskの直後(そしてnextTask = nextTask + 1の処理が行われる前)に 他のスレッドがmyTask = nextTaskの処理を行ってしまい、同じ仕事が複数回行われてしまう可能性が出てきます。

14.1 ☆演習課題:critical指示構文

下記に示すプログラムは1から10000までの数値の合計を逐次計算と並列計算でそれぞれ求めてその結果を表示します。 しかしながらこのままでは(必ずしも)正しく動きません。 このコードにcritical指示構文を追加して正しく動くように書き換えて下さい。
[課題のコード]
program kadaiCritical
  implicit none
  integer,parameter :: N = 10000
  integer i, totalParallel, totalSerial
  !逐次計算で合計を求める
  totalSerial = 0
  do i=1, N
    totalSerial = totalSerial + i
  end do
  totalParallel = 0
  !並列計算で合計を求める
!$omp parallel
!$omp do
  do i=1, N
    totalParallel = totalParallel + i
  end do
!$omp end do
!$omp end parallel
  print *, "Total(serial)   :", totalSerial
  print *, "Total(parallel) :", totalParallel
end program

[正しい実行結果の例]
 Total(serial)   : 50005000
 Total(parallel) : 50005000
解答例:kadaiCritical.f90


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

Results matter. Trust NAG.
Privacy Policy | Trademarks