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.