This chapter contains the following sections:
“Overview of Directives and Assertions” explains the concept of directives and assertions.
“Circumventing Power Fortran” explains how to use directives to bypass Power Fortran's analysis and leave areas of code unchanged.
“Fine-Tuning Scalar Optimizations” describes how you can use directives to fine-tune scalar optimizations.
“Fine-Tuning Inlining and IPA” explains how to use directives for inlining and IPA.
“Running Code Serially” explains how to use directives and assertions to stop Power Fortran from running specific code in parallel.
“Running Code in Parallel” explains how to use directives and assertions to tell Power Fortran that it is safe to run specific parts of code in parallel.
“Using Equivalenced Variables” explains how you can inform the compiler that your code uses or does not use equivalenced variables.
“Using Assertions” tells how to enable or disable compiler recognition of assertions.
“Using Aliasing” explains the assertions that enable or disable types of aliasing.
“Fine-Tuning Global Assumptions” describes how you can use assertions to fine-tune global assumptions.
“Ignoring Data Dependencies” explains how to tell Power Fortran that apparently data-dependent code is safe to run in parallel.
After you run a Fortran source program through Power Fortran once, you can use directives and assertions to fine-tune program execution. The listing file shows where and why Power Fortran did not parallelize the code. You can also use WorkShop Pro MPF to review the Power Fortran analysis of your program.
You can use directives and assertions to force Power Fortran to execute portions of code in various ways. Command-line directives apply to the program as a whole. You can use the –pfa,–directives command-line option to selectively enable or disable certain directives and assertions. Refer to “Recognizing Directives” for information about the –directives option.
If you want finer control for parallelizing a critical loop or inlining a particular occurrence of a routine, specify directives and assertions directly in the code. You can also use directives and assertions to keep Power Fortran from converting code to run in parallel. In other cases you might want to explicitly force Power Fortran to run segments of code in parallel even though it normally would not.
Because Power Fortran does not check the correctness of assertions, they can be unsafe. If you specify an incorrect assertion, the code generated by Power Fortran might give different answers from the scalar program. If you suspect unsafe assertions are causing problems, use the –nodirectives command-line option or the C*$* NO ASSERTIONS directive to tell Power Fortran to ignore all assertions.
Directives enable, disable, or modify a feature of the compiler. Essentially, directives are command-line options specified within the input file instead of on the command line. Unlike command-line options, directives have no default setting. To invoke a directive, you must either toggle it on or set a desired value for its level.
Directives allow you to enable, disable, or modify a feature of the compiler in addition to, or instead of, command-line options. Directives placed on the first line of the input file are called global directives. The compiler interprets them as if they appeared at the top of each program unit in the file. Use global directives to ensure that the program is compiled with the correct command-line options. Directives appearing anywhere else in the file apply only until the end of the current program unit. The compiler resets the value of the directive to the global value at the start of the next program unit. (Set the global value using a command-line option or a global directive.)
Some command-line options act like global directives. Others override directives. Many directives have corresponding command-line options. If you specify conflicting settings in the command line and a directive, the compiler chooses the most restrictive setting. For Boolean options, if either the directive or the command line has the option turned off, it is considered off. For options that require a numeric value, the compiler uses the minimum of the command-line setting and the directive setting.
Table 7-1 lists the directives supported by the compiler. In addition to the standard Silicon Graphics directives, the compiler supports the Cray and VAST directives listed in the table. The compiler maps these directives to corresponding Silicon Graphics assertions. Refer to “Assertions” for details.
Directive | Compatability |
---|---|
C*$* ARCLIMIT(n) | Silicon Graphics |
C*$* [NO] ASSERTIONS | Silicon Graphics |
C*$* EACH_INVARIANT_IF_GROWTH(n) | Silicon Graphics |
C*$* [NO] INLINE | Silicon Graphics |
C*$* [NO] IPA | Silicon Graphics |
C*$* MAX_INVARIANT_IF_GROWTH(n) | Silicon Graphics |
C*$* OPTIMIZE(n) | Silicon Graphics |
C*$* ROUNDOFF(n) | Silicon Graphics |
C*$* SCALAR OPTIMIZE(n) | Silicon Graphics |
C*$* UNROLL(integer[,weight]) | Silicon Graphics |
CDIR$ NO RECURRENCE | Cray |
CVD$ [NO] DEPCHK | VAST |
CVD$ [NO] LSTVAL | VAST |
Assertions provide the compiler with additional information about a source program. Sometimes assertions can improve optimization results. Use them only when speed is essential. Assertions can be unsafe because the compiler cannot verify the accuracy of the information provided. If you specify an incorrect assertion, the compiler-generated code might produce results different from those of the original serial program. If you suspect unsafe assertions are causing problems, use the –pfa,–nodirectives command-line option or the C*$* NO ASSERTIONS directive to tell the compiler to ignore all assertions.
Table 7-2 lists the supported assertions and their duration.
Table 7-2. Assertions and Their Duration
Assertion | Duration |
---|---|
C*$* ASSERT [NO] ARGUMENT ALIASING | Until reset |
C*$* ASSERT [NO] BOUNDS VIOLATIONS | Until reset |
C*$* ASSERT [NO] EQUIVALENCE HAZARD | Until reset |
C*$* ASSERT NO RECURRENCE | Next loop |
C*$* ASSERT RELATION (name.xx.name) | Next loop |
C*$* ASSERT [NO] TEMPORARIES FOR CONSTANT ARGUMENTS | Next loop |
As with a directive, the compiler treats an assertion as a global assertion if it comes before all comments and statements in the file. That is, the compiler treats the assertion as if it were repeated at the top of each program unit in the file.
Some assertions (such as C*$* ASSERT RELATION) include variable names. If you specify them as global assertions, a program uses them only when those variable names appear in COMMON blocks or are dummy argument names to the subprogram. You cannot use global assertions to make relational assertions about variables that are local to a subprogram.
Many assertions, like directives, are active until the end of the program unit (or file) or until you reset them. Other assertions are active within a program unit, regardless of where they appear in that program unit.
Certain Cray and VAST directives function like Silicon Graphics assertions. The compiler maps these directives to the corresponding Silicon Graphics assertions. These directives are described along with the related assertions later in this chapter.
There is no guarantee that a specified assertion will have an effect. The compiler notes the information provided by the assertion and uses the information if it will help.
To understand how the compiler interprets assertions, you must understand the concept of assumed dependences. The following loop contains two types of dependences:
DO 10 i=1,n 10 X(i) = X(i-1) + X(m) |
X is an array, n and m are scalars, and nothing is known about the relationship between n and m. Between X(i) and X(i-1) there is a forward dependence, with a distance of one. Between X(i) and X(m), the compiler tries to find a relation, but cannot, because it does not know the value of m in relation to n. The second dependence is called an assumed dependence, because it is assumed but cannot be proven to exist.
Sometimes you might need to hand-tune a DO loop so that it runs in parallel. Use the directives in this section to prevent Power Fortran from analyzing your modified code.
The C$ DOACROSS directive tells the Fortran 77 compiler to generate parallel code for the following loop. When Power Fortran encounters this directive on input, it does not modify the accompanying loop and therefore does not interfere with any hand-tuning.
C$ DOACROSS is the standard method for parallelism in Fortran. This directive is the same directive that Power Fortran generates as a result of its analysis. Refer to the MIPSpro Fortran 77 Programmer's Guide for more information about the C$ DOACROSS directive and its optional clauses.
Power Fortran runs the following code as it appears:
C$ DOACROSS DO 10 I=1, 100 A(I) = B(I) 10 CONTINUE |
The C$& directive continues the C$ DOACROSS directive onto multiple lines; for example:
C$DOACROSS SHARE(ALPHA, BETA, GAMMA, DELTA, C$& EPSILON, OMEGA), LASTLOCAL (I, J, K, L, M, N), C$& LOCAL(XXX1, XXX2, XXX3, XXX4, XXX5, XXX6, XXX7, C$& XXX8, XXX9) |
The compiler supports several directives that allow you to fine-tune the scalar optimizations described in “Controlling Scalar Optimizations”.
The C*$* ARCLIMIT(integer) directive sets the minimum size of the internal table that the compiler uses for data dependence analysis. The greater the value for integer, the more information the compiler can keep on complex loop nests. The maximum value and default value for integer is 5000. When you specify this directive globally, it has the same effect as the –arclimit command-line option (refer to “Controlling Internal Table Size” for details).
The C*$* EACH_INVARIANT_IF_GROWTH and the C*$* MAX_INVARIANT_IF_GROWTH directives control limits on invariant IF floating. This process generally involves duplicating the body of the loop, which can increase the amount of code considerably. Refer to “Setting Invariant IF Floating Limits” for details about invariant IF floating.
The C*$* EACH_INVARIANT_IF_GROWTH(integer) directive limits the total number of additional lines of code generated through invariant IF floating in a loop. You can control this limit globally with the –each_invariant_if_growth command-line option (see “Setting Invariant IF Floating Limits”).
You can limit the maximum amount of additional code generated in a program unit through invariant IF floating with the C*$* MAX_INVARIANT_IF_GROWTH(integer) directive. Use the –max_invariant_if_growth command-line option to control this limit globally (see “Setting Invariant IF Floating Limits”).
These directives are in effect until the end of the routine or until reset by a succeeding directive of the same type.
Consider the following code:
C*$*EACH_INVARIANT_IF_GROWTH(integer) C*$*MAX_INVARIANT_IF_GROWTH(integer) DO I = ... C*$*EACH_INVARIANT_IF_GROWTH(integer) C*$*MAX_INVARIANT_IF_GROWTH(integer) DO J = ... C*$*EACH_INVARIANT_IF_GROWTH(integer) C*$*MAX_INVARIANT_IF_GROWTH(integer) DO K = ... section-1 IF ( ) THEN section-2 ELSE section-3 ENDIF section-4 ENDDO ENDDO ENDDO |
In floating the invariant IF out of the loop nest, the compiler honors the constraints set by the innermost directives first. If those constraints are satisfied, the invariant IF is floated from the inner loop. The middle pair of directives is tested and the invariant IF is floated from the middle loop as long as restrictions established by these directives are not violated. The process of floating continues as long as directive constraints are satisfied.
The C*$* OPTIMIZE(integer) directive sets the optimization level in the same way as the –optimize command-line option. As you increase integer, the compiler performs more optimizations, and therefore takes longer to compile. Valid integer values are:
0 | Disables optimization. | |
1 | Performs only simple optimizations. Enables induction variable recognition. | |
2 | Performs lifetime analysis to determine when last-value assignment of scalars is necessary. | |
3 | Recognizes triangular loops and attempts loop interchanging to improve memory referencing. Uses special case data dependence tests. Also, recognizes special index sets called wrap-around variables. | |
4 | Generates two versions of a loop, if necessary, to break a data dependence arc. | |
5 | Enables array expansion and loop fusion. |
Refer to “Controlling Scalar Optimizations” for examples.
The C*$* ROUNDOFF(integer) directive controls the amount of variation in round off error produced by optimization in the same way as the –roundoff command-line option. Valid values for integer are as follows:
0 | Suppresses any transformations that change round-off error. | |
1 | Performs expression simplification, which might generate various overflow or underflow errors, for expressions with operands between binary and unary operators, for expressions that are inside trigonometric intrinsic functions returning integer values, and after forward substitution. Enables strength reduction. Performs intrinsic function simplification for max and min. Enables code floating if –scalaropt is at least 1. Allows loop interchanging around serial arithmetic reductions, if –optimize is at least 4. Allows loop rerolling, if –scalaropt is at least 2. | |
2 | Allows loop interchanging around arithmetic reductions if –optimize is at least 4. For example, the floating point expression A/B/C is computed as A/(B*C). | |
3 | Recognizes REAL (float) induction variables if –scalaropt is greater than 2 or –optimize is at least 1. Enables sum reductions. Enables memory management optimizations if –scalaropt=3 (see “Performing Memory Management Transformations” for details). |
The C*$* SCALAR OPTIMIZE(integer) directive controls the amount of standard scalar optimizations that the compiler performs. Unlike the –pfa,–scalaropt command-line option, the C*$* SCALAR OPTIMIZE directive sets the level of loop-based optimizations (such as loop fusion) only, and not straight-code optimizations (such as dead-code elimination). Valid values for integer are as follows:
0 | Disables all scalar optimizations. | |
1 | Enables simple, loop-based, scalar optimization—changing IF loops to DO loops, simple code floating out of loops, and forward substitution of variables. | |
2 | Enables the full range of loop-based scalar optimizations—induction variable recognition, loop rerolling, loop unrolling, loop fusion, and array expansion. | |
3 | Enables memory management transformations if –roundoff=3. Refer to “Performing Memory Management Transformations” for details. |
The C*$* UNROLL(integer[,weight]) directive controls how the compiler unrolls scalar loops. Loops that cannot be optimized for concurrent execution usually execute more efficiently when they are unrolled. This directive is recognized only when you specify –pfa,–scalaropt=2.
The compiler unrolls the loop proceeding the C*$* UNROLL directive until either the number of operations in the loop equals the weight parameter or the number of iterations reaches the integer parameter, whichever occurs first. The –unroll and –unroll2 command-line options act like a global C*$* UNROLL directive. See “Enabling Loop Unrolling” for detailed examples.
The C*$* UNROLL directive is in effect only for the loop immediately following it, unlike other directives.
Chapter 6, “Inlining and Interprocedural Analysis,” explains how to use inlining and IPA on an entire program. You can fine-tune inlining and IPA using the C*$* [NO] INLINE and C*$* [NO] IPA directives.
The compiler ignores these directives by default. They are enabled when you specify any inlining or IPA command-line option, respectively, on the command line. The –inline_manual and –ipa_manual command-line options enable these directives without activating the automatic inlining algorithms.
The C*$* [NO] INLINE directive behaves like the –inline command-line option, but allows you to specify which occurrences of a routine are actually inlined. The format for this directive is
C*$*[NO]INLINE [(name[,name ... ])] [HERE|ROUTINE|GLOBAL] |
where
name | Specifies the routines to be inlined. If you do not specify a name, this directive will affect all routines in the program. | |
HERE | Applies the INLINE directive only to the next line; occurrences of the named routines on that next line are inlined. | |
ROUTINE | Inlines the named routines everywhere they appear in the current routine. | |
GLOBAL | Inlines the named routines throughout the source file. |
If you do not specify HERE, ROUTINE, or GLOBAL, the directive applies only to the next statement. The C*$* NO INLINE form overrides the –inline command-line option and so allows you to selectively disable inlining of the named routines at specific points.
In the following code fragment, the C*$* INLINE directive inlines the first call to beta but not the second:
do i =1,n C*$*INLINE (beta) HERE call beta (i,1) enddo call beta (n, 2) |
Using the specifier ROUTINE rather than HERE inlines both calls. This routine must be compiled with the –inline_man command-line option for the compiler to recognize the C*$* INLINE directive.
The C*$* [NO] IPA directive is the analogous directive for interprocedural analysis. The format for this directive is
C*$*[NO]IPA [(name [,name...])] [HERE|ROUTINE|GLOBAL] |
Use the following assertions and directives to keep Power Fortran from running specific code in parallel.
The C*$* ASSERT DO (SERIAL) assertion tells Power Fortran to run the loop immediately following it serially. Power Fortran also does not try to run any enclosing loop in parallel. However, it can still convert any loops nested inside the serial loop to run in parallel. For example, consider the following code.
DO 100 i = 1,n DO 100 j = 1, n C*$*ASSERT DO (SERIAL) DO 200 k = 1, n X(i,j,k) = X(i,j,k) * Y(i,j) 200 CONTINUE DO 300 k = 1, n X(i,j,k) = X(i,j,k) + Z(i,k) 300 CONTINUE 100 CONTINUE |
The assertion forces the DO 100 I loop, the DO 100 J loop, and the DO 200 K loop to be serial. The compiler can still optimize the DO 300 K loop. In this case, the compiler does not distribute the I or J loops to try to obtain an optimizable loop.
See also “C*$* ASSERT DO PREFER (SERIAL)”.
MIPSpro Power Fortran 77 supports the corresponding Cray directive, CDIR$ NEXT SCALAR. Power Fortran interprets this directive as if it were a C*$* ASSERT DO (SERIAL) assertion and generates scalar code for the next DO loop.
The C*$* ASSERT DO PREFER (SERIAL) assertion tells the compiler to prefer any ordering in which the loop following the assertion remains serial. Unlike C*$* ASSERT DO (SERIAL), this assertion does not inhibit optimization of outer loops. This assertion directs Power Fortran to leave the DO loop alone, regardless of the setting of the optimization level. You can use this assertion to control which loop (in a nest of loops) Power Fortran chooses to run in parallel.
The following code segment is an example of how to use the assertion:
DO 100 I = 1, N C*$*ASSERT DO PREFER (SERIAL) DO 100 J = 1, M A(I,J) = B(I,J) 100 CONTINUE |
In the DO loop above, the assertion requests that the J loop be serial. In this construction, Power Fortran tries to run the I loop in parallel but not the J loop. This capability is useful when you know the value of M to be very small or less than N. This assertion applies only to the DO loop that appears directly after the assertion.
This section explains the directives and assertions that allow Power Fortran to determine that specific areas of code are safe to run in parallel.
The C*$* [NO] CONCURRENTIZE directive converts eligible loops to run in parallel. The NO version prevents Power Fortran from converting loops to run in parallel. These directives override the –[no] concurrentize command-line option.
For example, if your program contains the C*$* NO CONCURRENTIZE directive, parallelization is disabled even if you compile with –concurrentize. When specified globally, these directives have the same effect as the –concurrentize and –noconcurrentize options (see “Running Code in Parallel” for details).
Power Fortran supports the VAST directive CVD$CONCUR. This directive runs a loop in parallel to optimize performance. Power Fortran interprets this directive as if it were the C*$*CONCURRENTIZE directive.
The C*$* ASSERT DO PREFER (CONCURRENT) assertion directs Power Fortran to run a particular nested loop in parallel if possible. Power Fortran runs another of the nested loops in parallel only if a condition prevents running the selected loop in parallel.
This assertion applies only to the DO loop immediately after it.
Consider the following code:
C*$* ASSERT DO PREFER (CONCURRENT) DO 100 I = 1, N DO 100 J = 1, M A (I, J) = B (I, J) 100 CONTINUE |
This code directs Power Fortran to prefer to run the I loop in parallel. However, if a data dependence conflict prevents running the I loop in parallel, Power Fortran might run the J loop in parallel.
The –noconcurrentize command-line option and the C*$* NO CONCURRENTIZE directive prevent Power Fortran from generating concurrent code, even if you specify the C*$* ASSERT DO PREFER (CONCURRENT) assertion.
The C*$* ASSERT [NO] EQUIVALENCE HAZARD assertion tells the compiler that your code does not use equivalenced variables to refer to the same memory location inside one loop nest. Normally, EQUIVALENCE statements allow your code to use different variable names to refer to the same storage location.
The –pfa,-assume=e command-line option acts like the global C*$* ASSERT EQUIVALENCE HAZARD assertion (see “Controlling Global Assumptions”). The C*$* ASSERT EQUIVALENCE HAZARD assertion is active until you reset it or until the end of the program.
The C*$* [NO] ASSERTIONS directive instructs the compiler to accept or ignore assertions. The C*$* NO ASSERTIONS version is in effect until the next C*$* ASSERTIONS directive or the end of the program unit.
If you specify the –directives command-line option without the assertions parameter (that is, a), the compiler will ignore assertions regardless of whether the file contains the C*$* ASSERTIONS directive. Refer to “Recognizing Directives” for details on the –directives command-line option.
The C*$* ASSERT RELATION(name.xx.name) assertion indicates the relationship between two variables or between a variable and a constant. name is the variable or constant, and xx is any of the following: GT, GE, EQ, NE, LT, or LE. This assertion applies only to the next DO statement.
The C*$* ASSERT RELATION assertion includes variable names (name and xx). When specified globally, this assertion is used only when the variable names appear in COMMON blocks or are dummy arguments to a subprogram. You cannot use global assertions to make relational assertions about variables that are local to a subprogram.
As an example of the use of the C*$* ASSERT RELATION assertion, consider the following code:
DO 100 I = 1, N A (I) = A (I+M) + B (I) 100 CONTINUE |
If you know that M is greater than N, use the following assertion to give this information to the compiler:
C*$* ASSERT RELATION (M .GT. N) DO 100 I = 1, N A (I) = A (I +M) + B (I) 100 CONTINUE |
Knowing that M is greater than N, the compiler can generate parallel code for this loop. If M is less than N at run time, the answers produced by the code run in parallel could differ from the answers produced by the original code run serially.
![]() | Note: Many relationships of this type can be cheaply tested for at run time. The compiler attempts to answer questions of this sort by generating an IF statement that explicitly tests the relationship at run time. Occasionally, the compiler needs assistance, or you might want to squeeze that last bit of performance out of some critical loop by asserting some relationship rather than repeatedly checking it at run time. |
Use the assertions described in this section to fine-tune the global assumptions discussed in “Controlling Global Assumptions”.
The C*$* ASSERT [NO] BOUNDS VIOLATIONS assertion indicates that array subscript bounds may be violated during execution. If your program does not violate array subscript bounds, do not specify this assertion. When specified, this assertion is active until reset or until the end of the program. For formal parameters, the compiler treats a declared last dimension of (1) the same as (*).
The –pfa,–assert=b command-line option acts like a global C*$* ASSERT BOUNDS VIOLATIONS assertion.
In the example below, the compiler assumes the first loop nest is standard conformant, and therefore optimizes both loops. The loops can be interchanged to improve memory referencing because no A(I,J) overwrites an A(I',J+1). In the second nest, the assertion warns the compiler that the loop limit of the first array index (I) might violate declared array bounds. The compiler plays it safe and optimizes only the right array index.
![]() | Note: The compiler always assumes that array references are within the array itself, so the rightness index is concurrentizable. |
DO 100 I = 1,M DO 100 J = 1,N A(I,J) = A(I,J) + B (I,J) 100 CONTINUE C*$*ASSERT BOUNDS VIOLATIONS DO 200 I = 1,M DO 200 J = 1,N A(I,J) = A(I,J) + B (I,J) 200 CONTINUE |
The example above becomes:
C$DOACROSS SHARE(N,M,A,B),LOCAL(J,I) DO 2 J=1,N DO 2 I=1,M A(I,J) = A(I,J) + B (I,J) 2 CONTINUE C C*$*ASSERT BOUNDS VIOLATIONS DO 4 I=1,M C$DOACROSS SHARE(N,I,A,B),LOCAL(J) DO 3 J=1,N A(I,J) = A(I,J) + B (I,J) 3 CONTINUE 4 CONTINUE |
The C*$* ASSERT NO EQUIVALENCE HAZARD assertion tells the compiler that equivalenced variables will not be used to refer to the same memory location inside one DO loop nest. Normally, EQUIVALENCE statements allow different variable names to refer to the same storage location. The –pfa,–assume=e command-line option acts like a global C*$* ASSERT NO EQUIVALENCE HAZARD assertion. This assertion is active until reset or until the end of the program.
In the following example, if arrays E and F are equivalenced, but you know that the overlapping sections will not be referenced in this loop, then using C*$* ASSERT NO EQUIVALENCE HAZARD allows the compiler to concurrentize the loop.
EQUIVALENCE ( E(1), F(101) ) C*$* ASSERT NO EQUIVALENCE HAZARD DO 10 I = 1,N E(I+1) = B(I) C(I) = F(I) 10 CONTINUE |
The example above becomes:
EQUIVALENCE (E(1), F(101)) C*$* ASSERT NO EQUIVALENCE HAZARD C$DOACROSS SHARE(N,E,B,C,F),LOCAL(I) DO 10 I=1,N E(I+1) = B(I) C(I) = F(I) 10 CONTINUE |
Sometimes the compiler does not perform certain transformations when their effects on the rest of the program are unclear. For example, usually the IF-to-intrinsic transformation changes the following code
SUBROUTINE X(I,N) IF (I .LT. N) I = N END |
into the following:
SUBROUTINE X(I,N) I = MAX(I,N) END |
But if the actual parameter for I were a constant such as the following,
CALL X(1,N) |
it would appear that the value of the constant 1 was being reassigned. Without additional information, the compiler does not perform transformations within the subroutine.
Most compilers automatically put constant actual arguments into temporary variables to protect against this case. The C*$*ASSERT TEMPORARIES FOR CONSTANT ARGUMENTS assertion or the –pfa,–assume=c command-line option (the default) informs the compiler that constant parameters are protected.
The NO version directs the compiler to avoid transformations that might change the values of constant parameters.
Power Fortran avoids running code in parallel that it believes to be data-dependent. Use the assertions described in the following sections to override this behavior.
Use the C*$* ASSERT DO (CONCURRENT) assertion to tell Power Fortran to ignore assumed data dependencies. Normally Power Fortran is conservative about converting loops to run in parallel.
When Power Fortran determines that it can run a loop in parallel, it categorizes the loop into one of three groups:
yes, it is safe to run the loop parallel
no, it is not safe to run the loop in parallel
not sure (cannot be determined)
Normally, Power Fortran does not run the loops it is unsure about in parallel. It assumes there are data dependencies. C*$* ASSERT DO (CONCURRENT) tells Power Fortran to go ahead and run these “not sure” loops in parallel.
![]() | Note: If Power Fortran identifies a loop as containing definite data dependencies (as opposed to dependencies it assumes, but is not sure of), it does not run the loop in parallel even if you specify a C*$* ASSERT DO (CONCURRENT) assertion. |
Power Fortran interprets the Cray directive CDIR$ IVDEP as if it were a C*$* ASSERT DO (CONCURRENT) assertion. Some dependencies that are safe to run on Cray hardware are not safe to run on Silicon Graphics hardware. Therefore, to avoid incorrect parallelization of loops, recognition of this assertion is turned off by default.
The C*$* ASSERT CONCURRENT CALL tells Power Fortran to ignore assumed dependencies that are caused by a subroutine call or a function reference. However, you must ensure that the subroutines and referenced functions are safe for parallel execution. This assertion applies to all subroutine and function references in the accompanying loop, which must appear on the next line.
Power Fortran interprets the VAST directive CDIR$ CNCALL as if it were a C*$* ASSERT CONCURRENT CALL assertion. Some dependencies that are safe to run on Cray hardware are not safe to run on Silicon Graphics hardware. Therefore, recognition of this assertion is turned off by default.
The C*$* ASSERT NO RECURRENCE(variable) assertion tells the compiler to ignore all data dependence conflicts caused by variable in the DO loop that follows it. For example, the following code tells the compiler to ignore all dependence arcs caused by the variable X in the loop:
C*$* ASSERT NO RECURRENCE (X) DO 10 i= 1,m,5 10 X(k) = X(k) + X(i) |
Not only does the compiler ignore the assumed dependence, it also ignores the real dependence caused by X(k) appearing on both sides of the assignment.
The C*$* ASSERT NO RECURRENCE assertion applies only to the next DO loop. It cannot be specified as a global assertion.
The C*$* ASSERT PERMUTATION(array) assertion tells Power Fortran that array contains no repeated values. This assertion permits Power Fortran to run in parallel certain kinds of loops that use indirect addressing; for example:
DO I = 1, N A(INDEX(I)) = A(INDEX(I)) + B(I) ENDDO |
You can run this loop in parallel only if the array INDEX has no repeated values (so that each INDEX (I) is unique). Power Fortran cannot determine this, so it does not run such a loop in parallel. However, if you know that every element of INDEX() is unique, you can insert the following line before the loop to permit the loop to be run in parallel:
C*$* ASSERT PERMUTATION (INDEX)