This tutorial introduces you to the process of running a serial Fortran code on the SP. It assumes you are familiar with Fortran and its syntax, but not with compiling and linking programs under UNIX.
In this tutorial you will work through several examples, beginning with the very simplest compile and link. Then you will move on to other situations which are commonly encountered: using data files for I/O, using shell scripts, handling program units which are in separate files, and using the UNIX make program.
The xlf compiler accepts the full Fortran 90 language, with new statements, intrinsic functions, free-form input, procedure enhancements, and much more.
Fortran programs (i.e.,the source code) can be easily created and modified using the system editor of your choice. Once you have created and saved your source file, you can compile the program, link it with the necessary Fortran library routines, and then execute the program. The executable file is saved with the name a.out (by default) and it can be executed for different runs (i.e., with different input). Of course, if you change the source code, you will need to recompile and link to create an updated executable.
Create an empty subdirectory to work in so that the files from
this tutorial do not get mixed up with your other files.
In our example, we call this subdirectory "fortlab," but you can
call it something else if you wish.
Use the UNIX cp command to copy the tutorial files
to your subdirectory. The files that you need to run this tutorial
are in this directory: /afs/pdc.kth.se/public/www/training/Tutor/Fort.Intro
Type these commands:
mkdir fortlab
cd fortlab
cp /afs/pdc.kth.se/public/www/training/Tutor/Fort.Intro/my* .
cp /afs/pdc.kth.se/public/www/training/Tutor/Fort.Intro/*.f .
cp /afs/pdc.kth.se/public/www/training/Tutor/Fort.Intro/makefile .
cp command,
which refers to your current directory).
Issue the commands shown below to try out the example.
xlf myprog.f
./a.out
./ characters tell the loader to look
for the a.out file in your current working directory; without these,
you might get a "Command not found" message)
What if you don't want your executable named "a.out"? You can either rename
the file (with the mv command),
or you can use the -o flag on the xlf command
to override the default name of a.out. For example:
xlf -o myprog myprog.f
./myprog
./ as shown in the previous example.
-O2 (identical to -O) enables a base set of optimizations, designed to
generate fast object code with a relatively short compilation time.
-O3 provides the same optimizations as -O2, plus more thorough optimizations
that are memory or compile time intensive. Although its use is fine for
most codes, there is a possibility of changing the results of the program --
usually in the precision of the answers, although in rare cases program
results could be wrong. So you should
always check your program's answers against those produced without
optimization before routinely running the -O3 optimized code.
For example, compiling with the lower level of optimization:
xlf -o myprog -O2 myprog.f
./myprog
To run with the higher level of optimization:
xlf -o myprog -O3 myprog.f
If you want to ensure that optimizations done by the -O3 option do not alter the semantics of a program, use the -qstrict flag:
xlf -o myprog -O3 -qstrict myprog.f
The above optimization discussion is just a brief overview of one easy way for every programmer to optimize code. Additional information about optimizing serial Fortran code are discussed in the talk Single-Processor Performance Considerations for the SP2 and the corresponding lab Optimizing on a Single Processor, as well as IBM's XL Fortran manuals (see references at the end of this lab).
Fortran "read" (from unit 5) and "write" (to unit 6) statements default to stdin and stdout, respectively (which in turn default to the terminal). You can redirect stdin and stdout by the standard UNIX method. Run the program myprog1.f using the sample input file myprog1.input and directing the output to a file called myprog.output.
xlf -O myprog1.f
./a.out < myprog1.input > myprog.output
cat myprog.output
The above method works fine when you have one input file and one output file. However, programs which have more than one input or output file must use another method, in which different unit numbers (specified on read and write statements) are associated with specific files. The files used for input/output operations must be connected to a unit, which is a means of accessing a file. Units and files become connected through an OPEN statement. The syntax for an OPEN statement is given below:
OPEN( UNIT= un, FILE= fn )
un specifies an integer expression whose value
must be positive and nonzero, and
fn is a valid relative or absolute pathname.
The "UNIT=" keyword is optional and can be omitted.
This language construct is more fully described in the XL Fortran Language
Reference. It is important to remember that AIX distinguishes between
uppercase and lowercase characters. Thus,
Once a file is no longer needed by a program, it should be disconnected from a unit. Files are disconnected through a CLOSE statement or at the end of program execution. The syntax for a CLOSE statement is given below:
CLOSE( UNIT= un )
un specifies an integer expression whose value
must be positive and nonzero and must match the unit identifier that was
previously opened.
This language construct is more fully described in the XL Fortran Language
Reference.
Thus, to associate the file mydata.input with unit 10, include the following statements in your code:
OPEN( UNIT=10, FILE='./mydata.input')
...various READ and WRITE statements to unit 10 can go here...
CLOSE( UNIT=10 )
Look at the example program myprog2.f. Notice that the open statements associate unit 10 with the input file (myprog2.input) and unit 11 with an output file (myprog.output). Compile and execute the program using the steps below:
xlf -O myprog2.f
./a.out
cat myprog2.input
cat myprog.output
Shell scripts can become quite complicated, utilizing variables, pipes and redirection, as well as flow control commands. These topics are beyond the scope of this tutorial. More information can be found on these topics in any textbook on UNIX, and in our tutorial on Using and Writing Shell Scripts. Here we cover only the very basics of a shell script.
Simple shell scripts include groups of commands which can be processed by the shell. Commands are separated by newline characters (entered from the keyboard by pressing the RETURN key), or may be stacked on a single line and separated by semicolons. Comments are specified by pound (#) signs.
C shell scripts can be executed with the following command:
csh filename
filename is the valid pathname of a script file.
This utility will read the commands from the specified file and direct standard
input and standard output to the console. To display the commands as they are
passed to the shell, use the -v option.
For example, the following C shell script file, named myprog2.script, will compile, load and run the program from the previous section, myprog2.f.
# This is a sample C shell script # Execute this script by issuing the command: csh -v myprog2.script # xlf -O myprog2.f # compile and load this program ./a.out # run this programIssue the following command to run the script:
csh -v myprog2.script
-v flag displays
the commands as they are executed.
-v flag:
csh myprog2.script
xlf command.
In the following example, the main program, residing in the file
myprog3.f, calls a subroutine in a second file,
mysub3.f.
Look at those files before running this example.
xlf -o myprog3 -O myprog3.f mysub3.f
./myprog3
The compile step alone is done by specifying the -c flag
on the xlf command.
Instead of an executable file, only the object files (.o files) are
created. Then to link all the object files together to create the executable,
you issue the xlf command with the .o files as arguments.
Here are the specific commands for this example:
xlf -c -O myprog3.f mysub3.f
xlf -o myprog3 myprog3.o mysub3.o
xlf -c -O mysub3.f
xlf -o myprog3 myprog3.o mysub3.o
If you inherit a large program where the main program and all subroutines
are in one file, you can use fsplit to split the single file into
separate files for each program unit. See the man page for details on fsplit
make utility helps automate this process.
To take full advantage of make,
you need to keep each program unit (i.e., main program or subprogram) in
a separate source file as discussed in the previous section.
make builds
programs from dependency information stored in a file named makefile in
the working directory. A simple makefile has the following form:
target-file: prerequisite-file-list
TAB construction-commands
where target-file is the name of the file that
depends on the files in the prerequisite-file-list.
The construction-commands (one line or several lines)
must start with a TAB and are the commands that construct the target file.
As an example,
suppose that the executable file mycode depended on the object files
mycode.o and mysubs.o. An appropriate dependency line would be:
mycode: mycode.o mysubs.o
xlf -o mycode mycode.o mysubs.o
The following example uses the sample Fortran files
abc.f,
a.f,
b.f,
c.f
and the makefile
which you obtained earlier.
The main program resides in abc.f, and the subroutines reside in
in the files a.f, b.f and c.f.
Look at makefile and notice that there are commands to
create the executable (abc) and each of the .o files. By default,
the first target listed in the file is the one that will be created
when the make command is issued (in this case, the file abc).
Since abc depends on the files a.o, b.o, c.o and abc.o, all of the .o files
must exist (and be up-to-date); make will take care of checking
for them and re-creating them if necessary.
make
./abc
make
make can tell that the program is up-to-date.
touch command. Then re-build the program.
touch b.f
make
make was able to determine from the
rules in the makefile that, since b.f was updated, two targets needed to be
rebuilt: b.o and then abc.
The other .o files (upon which abc depends) were up-to-date and did not
need to be recompiled.
The above example is a very simple one, but there is much more you can do with
make. For more information and additional examples, see our
tutorial on make.
For complete information
on how make can be used, see the man page.
There are also textbooks that describe make in detail.
cd ../
rm -r labdir