In general, the compiler parallelizes a loop if you explicitly direct it to. There are exceptions—some loops the compiler will not parallelize.
The following are the primary detectable inhibitors that might prevent explicitly parallelizing a DO loop:
The DO loop is nested inside another DO loop that is parallelized.
This exception holds for indirect nesting, too. If you explicitly parallelize a loop that includes a call to a subroutine, then even if you request the compiler to parallelize loops in that subroutine, those loops are not run in parallel at runtime.
A flow control statement allows jumping out of the DO loop.
The index variable of the loop is subject to side effects, such as being equivalenced.
By compiling with -vpara and -loopinfo, you will get diagnostic messages if the compiler detects a problem while explicitly parallelizing a loop.
The following table lists typical parallelization problems detected by the compiler:
Table 10–3 Explicit Parallelization Problems
Problem |
Parallelized |
Warning Message |
---|---|---|
Loop is nested inside another loop that is parallelized. |
No |
No |
Loop is in a subroutine called within the body of a parallelized loop. |
No |
No |
Jumping out of loop is allowed by a flow control statement. |
No |
Yes |
Index variable of loop is subject to side effects. |
Yes |
No |
Some variable in the loop has a loop-carried dependency. |
Yes |
Yes |
I/O statement in the loop—usually unwise, because the order of the output is not predictable. |
Yes |
No |
Example: Nested loops:
... !$OMP PARALLEL DO do 900 i = 1, 1000 ! Parallelized (outer loop) do 200 j = 1, 1000 ! Not parallelized, no warning ... 200 continue 900 continue ... |
Example: A parallelized loop in a subroutine:
program main ... !$OMP PARALLEL DO do 100 i = 1, 200 <-parallelized ... call calc (a, x) ... 100 continue ... subroutine calc ( b, y ) ... !$OMP PARALLEL DO do 1 m = 1, 1000 <-not parallelized ... 1 continue return end |
In the example, the loop within the subroutine is not parallelized because the subroutine itself is run in parallel.
Example: Jumping out of a loop:
!$omp parallel do do i = 1, 1000 ! <- Not parallelized, error issued ... if (a(i) .gt. min_threshold ) go to 20 ... end do 20 continue ... |
The compiler issues an error diagnostic if there is a jump outside a loop marked for parallelization.
Example: A variable in a loop has a loop-carried dependency:
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 |
Here the loop is parallelized but the possible loop carried dependency is diagnosed in a warning. However, be aware that not all loop dependencies can be diagnosed by the compiler.