ナビゲーション:前へ 上へ 次へ
ナビゲーション:前へ 上へ 次へ
14 critical指示構文
共有データの更新を行う際に複数のスレッド間で競合が発生し、意図した結果が得られない場合があります。 critical指示構文を使うと他のスレッドと同時に実行されないことが保証される領域(クリティカルセクション等と呼ばれる)を指定することができます。以下に参考図を示します。
理解を深める上で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
ナビゲーション:前へ 上へ 次へ
