並列計算いろは (その7)
前回(その6)で,OpenMP文で最も使う頻度の高いPARALLEL DOを学びました.その結びで「PARALLEL DOは書き方は簡単だが,使うに当たって慎重さが必要」と書きました.今回はそのことについて話しましょう.

 その前に並列プログラムを,もう一度整理します.図1に示すように,プログラムは大きく分けて,並列可能なプログラムと並列不可能なプログラムに分類できます.並列可能とは,
条件1:CPU単体で実行した場合と並列で実行した場合の実行結果が一致すること.
条件2:単体で実行した場合より並列で実行した場合の方が速いこと.







                  
    図1一般のプログラム
以上2つの条件を同時に満たす場合です.場合によっては,条件1を満たす場合のみを指す場合もあります.そうです.並列化しても,結果が正しくなければ何にもなりません.自動並列化機能−apoを使った場合に並列化しないのは,どのようなときだったでしょうか?

1)do ループが小さいとき.
2)do ループ内にSUBROUTINE callがあるとき.
3)do ループ内にこのループ外に分岐するIF(条件)go to文があるとき.
4)変数に依存性があるとき.などです.

1)は並列化すると前述の条件2に触れるから,並列化しなくて当然です.2),3)はどうしてでしょうか.それは並列化した計算と,単体で計算した場合の結果が違う可能性があるからです.
コンパイラの自動並列化機能-apoでは,並列化しませんが,OpenMPを書いて並列化することもできます.例えばIF(条件)go to ループ外と書いてあっても,プログラムを書いた人なら,その条件を満たすことがないといったような事はわかっているはずです.そのような場合は,
Open-MP文C$OMP PARALLEL DOを書いて強制的に並列化しても,正しい結果が得られます.

 さあそれでは4)の変数に依存性があるとは,どのような事を言うのでしょうか.例1を見て下さい.








a(3)はp0で書きこまれて新しくなり,一方p2では読みこまれますが,その内容が新a(3)であるのか,旧a(3)であるのかは,p2の実行タイミングで変ります.この例のように,書き込みと読み込みが同時に行われる変数を,依存性があるといいます.この場合にOpenMPを使って強制的に並列化すると,結果は単体で実行した結果と違ってきます.OpenMPは言われた通りに,結果の正否には関係なく強制的に並列化を行います.その意味で「OpenMPを使うには,慎重さが必要」なのです.縮約がある計算も依存性がある場合に含まれますが,それに対しては
C$OMPPARALLEL DO REDUCTION(+:s)
とすればよいということを,前回に述べました.依存性については,
http://wwweic.eri.u-tokyo.ac.jp/computer/
中級者向けコース資料を参照.