This chapter contains the following sections:
“Overview of Output Files” discusses the Power Fortran output files and provides examples of them.
“Formatting the Listing File” explains how to change the format of the standard listing file.
“Interpreting Default Listing Information” explains the contents of the listing file.
“Sample Listing Files” provides code examples along with an interpretation of each.
Power Fortran can generate three types of output files:
listing file (.l)
transformed Fortran source file (.m) that contains the original source program with the multiprocessing directives inserted by Power Fortran
an input file for use with WorkShop Pro MPF (.anl)
When you specify the list argument to –pfa, Power Fortran produces a line-numbered listing file. If you specify the keep argument instead, Power Fortran produces the numbered listing file, transformed Fortran source file, and the WorkShop Pro MPF file. (For details about invoking Power Fortran, refer to Chapter 2, “How to Use Power Fortran.”)
For example, consider the following code segment, sample.f:
subroutine sample (a,b,c) dimension a(1000),b(1000),c(1000) do 10 i = 1, 1000 10 a(i) = b(i) + c(i) end
Compiling sample.f as follows
% f77 -pfa list -c sample.f
generates the following listing file, sample.l:
Footnotes Actions Do Loops Line DIR 1 # 1 "sample.f" 2 subroutine sample(a,b,c) 3 dimension a(1000),b(1000),c(1000) SO C +-------- 4 do 10 i = 1,1000 SO *_______ 5 10 a (i) = b(i) + c(i) 6 end Abbreviations Used SO scalar optimization DIR directive C concurrentized Loop Summary From To Loop Loop at Loop# line line label index nest Status 1 4 5 Do 10 I 1 concurrentized
Power Fortran placed a C before the first statement of the DO loop in the listing file, sample.l. The Abbreviations Used table shows that C stands for “concurrentized,” which means that Power Fortran determined that it can safely run the loop in parallel. The Loop Summary table at the bottom of sample.l shows that the status of the loop is concurrentized.
|Note: The first line number directive appears in the listing because it was actually added by cpp before Power Fortran ran.|
You can customize a Power Fortran listing file by
paginating the listing
selecting the information to be printed
disabling specific message classes
If you do not specify the –lines option, Power Fortran prints 55 lines per page.
The –listoptions=list option (or –lo=list) specifies the information to include in the listing file (.l), where list is any combination of the options in Table 3-1. The default is –listoptions=ol.
Calling tree at the end of the program listing.
Transformed program file annotated with line numbers in the source program. Error messages and debugging information can refer to the original source rather than the transformed source. This argument is specified by default.
List of the Power Fortran options used at the end of each program unit.
Loop-by-loop optimization table.
Program unit names, as processed, to the standard error file. This option is added automatically as part of an f77 –v compilation.
Annotated listing of the original program.
Processing performance statistics.
Summary of optimizations performed.
Annotated listing of the transformed program.
The following command compiles the program source.f with Power Fortran and includes an annotated listing of the original program and a summary of the optimizations performed in the listing file:
% f77 -pfa -pfa,-listoptions=ls source.f
Use the –suppress=list option (or –su=list) to disable individual classes of Power Fortran messages that are normally included in the listing (.l) file. These messages range from syntax warnings and error messages to messages about the optimizations performed. list is any combination of the options in Table 3-2.
Message Class Disabled
Unable to run loop in parallel
Warning of syntax error (Power Fortran adds the –suppress=w option automatically if you use the –w option to f77)
If you do not specify this option, Power Fortran prints messages of all classes.
Knowing when and where to modify your code means understanding the information in the Power Fortran listing. This understanding allows you to recognize where small changes to the source code will make a big difference in how much code is run in parallel. The listing file generated by Power Fortran lists the optimizations Power Fortran made to the code. For example, a message could say that, although three loops could have run in parallel, Power Fortran converted only the one it determined most profitable.
This section explains how to view the listing file online and then lists and describes the various fields.
The listing file is in 132-column format. To view the file, open a window with 132 columns and 40 rows by entering
% wsh -s132,40
A default Power Fortran listing file includes
DO loop markings
syntax errors/warning messages
In the listing transformed by Power Fortran, a statement labeled with a line number, such as 21, is the same as line 21 from the original program or has been derived from that line. These line numbers are useful when inspecting the transformed program listing and when debugging. Power Fortran sometimes generates several lines of code from a single line of the original program; in this case, each new line of code is labeled with the same number as the line of the original program from which it was generated. Consequently, many lines of the transformed program listing carry the same number because they are related to one line of the original program listing.
The listing file displays DO loops graphically in a column headed DO Loops. Power Fortran surrounds each DO loop (up to nest level 10) with a loop delimiter character. The delimiters form brackets around each loop nest level. Each character listed in Table 3-3 has a specific meaning.
Generic DO loop
Power Fortran can run loop in parallel
A statement contained within n DO loops has n of these loop delimiters on that line. For example, the following statements are contained within one DO loop and therefore have only one |:
DO Loops Line +------- 173 DO 100 M=2,MAX(MFLD,2) | 174 IADR = ISECT(M) | 175 IADR1= ISECT(M-1) | 176 PNM(IADR)=(ANM(IADR) *PNM(IADR1)) |_______ 177 100 PPNM(IADR)= -(ANM(IADR) *PNM(IADR1))
Power Fortran uses the footnotes listing to give important details concerning its actions. Power Fortran numbers and prints the footnotes at the bottom of each program unit under the Footnote List heading. References to the footnotes are displayed in the listing under the Footnotes column. For example, this footnote
13 DD 1790 IF (B(I) .LE. 6) IB(J*I) = I+J
appears under Footnote List at the end of the program unit
13: data dependence Data dependence involving this line due to variable IB.
In this example, 13 is the footnote number, DD (data dependence) is the explanation for the Power Fortran action, and the IF statement on line 1790 refers to the original source line number.
When a program has syntax errors, the listing file describes the error next to the lines that start with the symbol ### in the Footnotes column. These messages are also printed to stderr, which is usually your terminal.
Footnotes Actions DO Loops Line 1 SUBROUTINE Z(A,B,N) 2 REAL A(N), B(N) +------- 3 DO 20 I=1,N ! 4 X=A(I) ! 5 Y=B(I) ! ______ 6 20 C(I)=X+Y ### line (6) ### error Array not declared or statement function declared after executable statements. ### error A do loop ends on a non-executable statement. 7 PRINT *,X 8 END
When Power Fortran translates or modifies a statement, it uses abbreviations in the Actions column of the listing file to identify the statements. Power Fortran lists an abbreviated explanation of its actions at the bottom of the listing. For the DIR and V classes, the class itself serves as the message without detailed messages. All other classes have associated messages.
Table 3-4 lists and explains the values that can appear in the Actions column.
(Data Dependence) Indicates that data dependence prevented Power Fortran from running this statement in parallel.
(Directive) Used in conjunction with the footnotes and concerns compiler directives. If you code a compiler directive and that line does not have the DIR abbreviation in the listing, Power Fortran will not recognize the directive. Check the setting of the –directives command-line option and the syntax of the directive.
(Error) Indicates syntax errors. These messages can refer to missing or extra characters, illegal keywords, or text placed in the wrong column. Power Fortran cannot do anything with such code. The equivalent transformed source file (.m) contains a copy of this program unit that Power Fortran has not modified.
(Extension) Shows where a construct in the original program is not allowed in the language Power Fortran produces. In some cases, an operation or type is allowed in the input language but not in the output language.
(Information) Provides noncritical information.
(Insertion) Indicates that Power Fortran added a statement.
(Loop Reordering) Indicates that Power Fortran has modified a Fortran 77 statement in the process of interchanging loops. If during optimization Power Fortran ascertains that an outer loop would be more efficient as an inner loop, and it can legally reorder the loops, Power Fortran places the outer loop inside. In the process of this reordering, Power Fortran might have to change loop bounds (for triangular loops), distribute loops, or float IF assignments. Only the statements modified for the exchange are marked.
(Miscellaneous) Indicates that some Power Fortran information has been lost. This message does not always mean that something is wrong with the program.
(Nonconcurrent Statement) Indicates that Power Fortran did not try or was unable to run the statement in parallel. For example, when a subroutine call is involved in a loop, Power Fortran generates this message.
(Program Too Large—Not Optimized) Indicates that the program unit being processed is too large for Power Fortran to optimize, because of Power Fortran data structure size limitations. When Power Fortran optimizes programs, it adds statements that might also overflow the fixed-size tables. In either case, Power Fortran stops optimization and passes the original program to the equivalent transformed source file (.m), informing you of this action. For Power Fortran to process the unit, you must split the program into smaller sections.
(Option Error) Indicates a syntax error in a Power Fortran option. This error does not stop the processing of a program unit.
(Output Translation Failure) Marks statements that have constructs that exist in the input language but that cannot be represented in the output language.
(Question) Indicates that Power Fortran tried to optimize a loop nest but discovered a data dependence it could not break at compile time without further information. You can usually answer this question with an appropriate assertion.
(Scalar Optimization) Marks places in the transformed listing where Power Fortran has optimized a scalar loop.
(Standardized) Marks where Power Fortran changed a program to improve the chance of finding code that it can optimize. This is often a conversion from an IF/GOTO into a block IF, loop rerolling, and conversion of an IF loop into a DO loop.
(Translator Error) Indicates an internal Power Fortran error. Power Fortran writes the notification to the standard error file and writes a trace back to the output file. Notify Silicon Graphics if you see this sort of bug (so it can be corrected) and, if possible, send Silicon Graphics the code that caused the trace back as well as the trace back itself. If you can reproduce the error in a small program unit, send that small program unit as well.
(Warning) Contains syntax warnings.
This section contains a few simple examples of Fortran code and the corresponding Power Fortran output. An actual source program would be much larger, and a single loop could contain several of the cases illustrated here. However, even in a large loop, you can deal with each problem individually.
Power Fortran cannot determine if it can run a loop in parallel when the code uses indirect indexing. A loop is indirectly indexed when it uses the value from some auxiliary array as the index value rather than the DO loop variable. The code
subroutine foo2(a,b,index,n) real a(n), b(n) integer index(n) c do i = 1, n a(index(i)) = a(index(i)) + b(i) enddo end
when submitted to Power Fortran, produces this listing file:
Footnotes Actions DO Loops Line DIR 1 # 1 "foo2.f" 1 subroutine foo2(a,b,index,n) 2 real a(n), b(n) 3 integer index(n) 4 1 Q SO +------- 5 do i = 1, n 2 DD SO ! 6 a(index(i)) = a(index(i)) + b(i) !_______ 7 enddo 8 end Abbreviations Used DD data dependence Q question SO scalar optimization DIR directive Footnote List 1: question Is “INDEX” a permutation vector? 2: data dependence Data dependence involving this line due to variable A. Loop Summary From To Loop Loop at loop# line line label index nest Status 1 6 8 Do I 1 scalar mode preferable
DD in the Actions column on line 6 of the listing warns that the variable a might carry a dependency. A dependency exists when one iteration of the loop writes to a location that is used by a different iteration of the loop. In this example, if the values of index(i) are ever the same for different values of i, then different iterations might use the same location in a. Therefore, this code contains a possible data dependence.
If you can guarantee that the values of index(i) are always different for each value of i, then there is no dependence (each iteration uses a different location in a). Question one on the Footnote List asks if index(i) is different for every value of i. A permutation vector is a list of numbers, each of which is different from the others. If you know that index is a permutation vector, then the loop is data-independent. An example of a permutation vector is a list of objects in which each object appears exactly once.
Explicitly state that index is a permutation vector by adding an assertion in the source.
subroutine foo2(a,b,index,n) real a(n), b(n) integer index(n) c*$*assert permutation (index) do i = 1, n a(index(i)) = a(index(i)) + b(i) enddo end
Now the listing file shows that Power Fortran finds the loop safe to run in parallel (indicated by the * DO loop delimiter):
Footnotes Actions DO Loops Line DIR 1 # 1 "foo2.f" 1 subroutine foo2(a,b,index,n) 2 real a(n), b(n) 3 integer index(n) DIR 4 c*$*assert permutation (index) 5 1 SO C +------- 6 do i = 1, n 2 SO * 7 a(index(i)) = a(index(i)) + b(i) *_______ 8 enddo 9 end Abbreviations Used SO scalar optimization DIR directive C concurrentized Loop Summary From To Loop Loop at loop# line line label index nest Status 1 7 9 Do I 1 concurrentized
|Note: As with all assertions, Power Fortran does not verify the truth of this assertion. When you make an assertion, be certain that it is always true for all possible input data.|
This example shows what happens when a loop contains a call to an external routine. The Fortran 77 code
subroutine foo3 (a,b,c,n) real a(n), b(n), c(n) external force c do i = 1, n a(i) = force (b(i), c(i)) enddo end
generates this listing:
Footnotes Actions DO Loops Line DIR 1 # 1 "foo3.f" 1 subroutine foo3(a,b,c,n) 2 real a(n), b(n), c(n) 3 external force 4 1 2 NO SO NCS +------ 5 do i = 1,n 3 NO SO NCS ! 6 a(i) = force (b(i), c(i)) !______ 7 enddo 8 end Abbreviations Used NO not optimized SO scalar optimization DIR directive NCS non-concurrent-stmt Footnote List 1: not optimized No optimizable statements found. 2: not optimized This loop contains an unoptimizable call to “FORCE”. 3: not optimized This statement contains an unoptimizable call to “FORCE”. Loop Summary From To Loop Loop at Loop# line line label index nest Status 1 6 8 Do I 1 unoptimizable call (FORCE)
Calling the function force prevents Power Fortran from automatically running the loop in parallel. Power Fortran identifies the function call as a non-concurrent-stmt. By its nature, a nonconcurrent statement prevents Power Fortran from assuming the loop is safe to run in parallel because Power Fortran cannot see into the routine to look for data dependencies.
If you know that force generates no data dependencies, then explicitly state this fact for the nonconcurrent statement.
subroutine foo3(a,b,c,n) real a(n), b(n), c(n) external force c*$*assert concurrent call do i = 1, n a(i) = force(b(i), c(i)) enddo end
Now that Power Fortran knows that the nonconcurrent statement involves no data dependency, Power Fortran will find the loop safe to run in parallel.
There is one subtlety in using the concurrent call assertion. When you use this assertion, Power Fortran makes no attempt to examine the called routine; it simply assumes that it is safe. However, Power Fortran is still left with the problem of correctly declaring the variables in the loop to be either SHARE or LOCAL. (Power Fortran does the best it can, but it can sometimes be fooled.) For example:
subroutine tricky (a,b,c,n,m) real a(*), b(*) external my_function c*$*assert concurrent call do i = 1, n a(i) = my_function (b(i), m) b(i) = a(i) + m enddo m = 0 end
The question is whether the variable m should be SHARE or LOCAL. If the routine my_function reads only the old value of m, then it should be SHARE. If my_function writes a new value of m, then it should be LOCAL. In the absence of any more clues, Power Fortran must go by what it can see; and what it can see is that within the loop, there are no visible assignments to m, and so Power Fortran will declare it to be SHARE. If in fact my_function is writing the value of m, then this is incorrect.
In this case, to give Power Fortran the hint it needs, add a visible assignment to m at the top of the loop. For example, consider the following code:
do i = 1, n m = 0 a(i) = my_function(b(i), m) b(i) = a(i) + m enddo
Here, Power Fortran can see an assignment to m and so declares it to be LOCAL. Note that if my_function is both reading the old value and writing a new value of m, then it was not legal to parallelize the loop.
This example shows how Power Fortran produces a single value from a set of values. Because the entire set of values is reduced to a single value, these operations are called reductions. Consider the following Fortran 77 code.
subroutine foo4(a,b,n,sum) real a(n), b(n), sum c sum = 0.0 do i = 1, n sum = sum + a(i)*b(i) enddo end
Using the previous code as input, Power Fortran produces this listing file:
Footnotes Actions DO Loops Line DIR 1 # 1 "foo3.f" 1 subroutine foo4(a,b,n,sum) 2 real a(n), b(n), sum 3 SO 4 sum = 0.0 SO +----- 5 do i = i, n 1 DD SO ! 6 sum = sum + a(i)*b(i) !_____ 7 enddo 8 end Abbreviations Used DD data dependence SO scalar optimization DIR directive Footnote List 1: data dependence Data dependence involving this line due to variable “SUM”. Loop Summary From To Loop Loop at Loop# line line label index nest Status 1 6 8 Do I 1 scalar mode preferable
Because different iterations of the loop read and write the same location (the variable sum), there is a dependence. However, this is a special case. Because sum just accumulates a total, you can accumulate subtotals in parallel and then combine the subtotals at the end.
Because the parallel version of the code adds the elements together in an order different from the single-process version, the round-off errors accumulate differently for the two versions of the code. Thus, the answer can differ slightly as you vary the number of processes used to run the code. In fact, if you use the dynamic scheduling option for the code, the answer might vary slightly from one run of the program to the next, even if you use the same number of processes on the same machine.
Most applications can safely ignore this variation in round-off error. If you do not care about this round-off error, tell Power Fortran to use parallel subtotals. To tell Power Fortran not to worry about round-off error, use either the C*$*ROUNDOFF(2) directive or the f77 command-line option –pfa,–roundoff=2. The resulting listing file is
Footnotes Actions DO Loops Line DIR 1 # 1 "foo3.f" 1 subroutine foo4(a,b,n,sum) 2 real a(n), b(n), sum 3 SO 4 sum = 0.0 SO C +----- 5 do i = i, n SO * 6 sum = sum + a(i)*b(i) *_____ 7 enddo 8 end Abbreviations Used SO scalar optimization DIR directive C concurrentized Footnote List 1: data dependence Data dependence involving this line due to variable “SUM”. Loop Summary From To Loop Loop at Loop# line line label index nest Status 1 6 8 Do I 1 concurrentized
Be aware that the round-off error produced by the parallel reduction operation is not necessarily any worse than the round-off error already present in the original serial version. It is simply different. If your application did not worry about the round-off error in the original, there is no reason to suppose that it should worry about it in the parallel version. If, on the other hand, your application takes special steps to reduce round off (for example, adding the numbers together in order from smallest absolute value to largest), then you should not use parallel reductions.