一般に、ユーザーがコンパイラにループを並列化するように明示的に指示している場合、コンパイラはそのようにします。ただし、例外もあり、ループによってはコンパイラが並列化を行わないものがあります。
次に、DO ループの明示的な並列化を妨げる抑制の中で、検出可能なものを示します。
DO ループが、並列化された別の DO ループ内に入れ子にされている場合
この例外は、間接の入れ子についても当てはまります。ユーザーがサブルーチンを呼び出しているループを明示的に並列化すると、コンパイラにそのサブルーチン内のループを並列化するように要求しても、これらのループは実行時に並列で実行されません。
フロー制御文により、DO ループから外部へのジャンプが許可されている場合
ループの添字変数が、等価になるなどの影響を受ける場合
-vpara および -loopinfo を指定してコンパイルすると、コンパイラが明示的にループを並列化している最中に問題を検出すると診断メッセージが発せられます。
次に、一般にコンパイラにより検出される並列化の問題を示します。
表 10–3 明示的な並列化時の問題
問題 |
並列化されます |
警告メッセージ |
---|---|---|
ループは、並列化されている別のループ内に入れ子にされています。 |
いいえ |
いいえ |
ループは、並列化されたループの本文内で呼び出されているサブルーチン内にあります。 |
いいえ |
いいえ |
フロー制御文で、ループから外部へのジャンプが許可されています。 |
いいえ |
はい |
ループの添字変数が、悪影響を受けています。 |
はい |
いいえ |
ループ内の変数に、ループ繰越の依存があります。 |
はい |
はい |
ループ内の入出力文 — 通常、出力順序は予想できないので賢明な処理ではありません。 |
はい |
いいえ |
例: 入れ子にされたループ
... !$OMP PARALLEL DO do 900 i = 1, 1000 ! 並列化されます (外側のループ) do 200 j = 1, 1000 ! 並列化されません。警告も発しません ... 200 continue 900 continue ... |
例: サブルーチン内で並列化されたループ
program main ... !$OMP PARALLEL DO do 100 i = 1, 200 <- 並列化されます ... call calc (a, x) ... 100 continue ... subroutine calc ( b, y ) ... !$OMP PARALLEL DO do 1 m = 1, 1000 <- 並列化されません ... 1 continue return end |
この例では、サブルーチン自体が並列で実行されているので、その中のループは並列化されません。
例: ループから外部へのジャンプ
!$omp parallel do do i = 1, 1000 ! <- 並列化されず、エラーとなります ... if (a(i) .gt. min_threshold ) go to 20 ... end do 20 continue ... |
並列化のマークが付いたループの外にジャンプがあると、コンパイラはエラーと診断します。
例: ループ依存性を持つループの変数
demo% cat vpfn.f real function fn (n,x,y,z) real y(*),x(*),z(*) s = 0.0 !$omp parallel do private(i,s) shared(x,y,z) do i = 1, n x(i) = s s = y(i)*z(i) enddo fn=x(10) return end demo% f95 -c -vpara -loopinfo -openmp -O4 vpfn.f "vpfn.f", line 5: Warning: the loop may have parallelization inhibiting reference "vpfn.f", line 5: PARALLELIZED, user pragma used |
ループは並列化されますが、可能なループ依存性は警告中で診断されます。しかし、ループ依存性のすべてがコンパイラによって診断できないことに注意してください。