<< Chapter < Page | Chapter >> Page > |
for (i=0; i<n; i++) {
a[i]= a[i+k] * b[i];
c[i]= c[i+j] * b[i];
}
Perhaps we know that there are no conflicts with references to
a[i]
and
a[i+k]
. But maybe we aren’t so sure about
c[i]
and
c[i+j]
. Therefore, we can’t say in general that there are no dependencies. However, we may be able to say something explicit about
k
(like “
k
is always greater than
-1
”), leaving
j
out of it. This information about the relationship of one expression to another is called a
relation assertion . Applying a relation assertion allows the compiler to apply its optimization to the first statement in the loop, giving us partial parallelization.
Notice that, if you were tuning by hand, you could split this loop into two: one parallelizable and one not.
Again, if you supply inaccurate testimony that leads the compiler to make unsafe optimizations, your answer may be wrong.
As we have seen elsewhere, when elements of an array are indirectly addressed, you have to worry about whether or not some of the subscripts may be repeated. In the code below, are the values of K(I) all unique? Or are there duplicates?
DO I=1,N
A(K(I)) = A(K(I)) + B(I) * CEND DO
If you know there are no duplicates in
K
(i.e., that
A(K(I))
is a permutation), you can inform the compiler so that iterations can execute in parallel. You supply the information using a
permutation assertion .
Equivalenced arrays in FORTRAN programs provide another challenge for the compiler. If any elements of two equivalenced arrays appear in the same loop, most compilers assume that references could point to the same memory storage location and optimize very conservatively. This may be true even if it is abundantly apparent to you that there is no overlap whatsoever.
You inform the compiler that references to equivalenced arrays are safe with a no equivalences assertion. Of course, if you don’t use equivalences, this assertion has no effect.
Each loop can be characterized by an average number of iterations. Some loops are never executed or go around just a few times. Others may go around hundreds of times:
C$ASSERT TRIPCOUNT>100
DO I=L,NA(I) = B(I) + C(I)
END DO
Your compiler is going to look at every loop as a candidate for unrolling or parallelization. It’s working in the dark, however, because it can’t tell which loops are important and tries to optimize them all. This can lead to the surprising experience of seeing your runtime go up after optimization!
A trip count assertion provides a clue to the compiler that helps it decide how much to unroll a loop or when to parallelize a loop. The assertion is made either by hand or from a profiler. Loops that aren’t important can be identified with low or zero trip counts. Important loops have high trip counts.
If your compiler supports procedure inlining, you can use directives and command-line switches to specify how many nested levels of procedures you would like to inline, thresholds for procedure size, etc. The vendor will have chosen reasonable defaults.
Notification Switch
Would you like to follow the 'High performance computing' conversation and receive update notifications?