Run-Time Efficiency [ HP FORTRAN 77/iX Programmer's Guide ] MPE/iX 5.0 Documentation
HP FORTRAN 77/iX Programmer's Guide
Run-Time Efficiency
The suggestions below help to decrease the time needed to run your
program.
Declare Integer and Logical Variables Efficiently
Declare integer and logical sizes equal to 32 bits (4 bytes) which is the
HP 3000 Series 900 word size. That is, use the defaults of INTEGER*4 and
LOGICAL*4.
Avoid Using Arrays
When possible, avoid using arrays because they are addressed indirectly;
that is, their address must be found first, and then the element at that
address must be found.
Use Efficient Data Types
When a choice of data type is possible for a variable, choose according
to the following hierarchy:
Table 6-1. Data Type Efficiency
-----------------------------------------------
| | |
| Type of Data Type | Order of Efficiency |
| | |
-----------------------------------------------
| | |
| Floating Point | REAL*4 (fastest) |
| | REAL*8 |
| | REAL*16 (slowest) |
| | |
-----------------------------------------------
| | |
| Integer | INTEGER*4 (fastest) |
| | INTEGER*2 (slowest) |
| | |
-----------------------------------------------
| | |
| Complex | COMPLEX*8 (fastest) |
| | COMPLEX*16 (slowest) |
| | |
-----------------------------------------------
However, as mentioned below, it is ideal to have variables that are used
together in expressions to be all the same type.
Avoid Mixed-Mode Expressions
Avoid mixed-mode expressions. For example, the assignment statement:
int = 1.0 + int
where int is an integer, requires converting int to a real number and
then converting the result back to an integer during execution. A more
efficient assignment statement would be:
int = 1 + int
Eliminate Slow Arithmetic Operators
When possible, replace slower arithmetic operations with faster
operations. The arithmetic operations are listed below from fastest to
slowest:
Addition and subtraction + - (Fastest)
Multiplication *
Division /
Exponentiation ** (Slowest)
In some cases, multiplication operations can replace exponentiation,
addition operations can replace multiplication, and multiplication
operations can replace division. For example,
i = j**2 can be written as i = j * j
a = 2.0 * b can be written as a = b + b
x = y / 10 can be written as x = y * 0.1
NOTE The last example might cause an error if you are porting your
program to another system because the internal representation of
0.1 might vary between systems.
Use Statement Functions
Use statement functions instead of short function subprograms. This
eliminates the overhead involved with loading parameters and avoids a
procedure call for the subprogram call. However, statement functions are
expanded in-line and thus increase the program size.
Reduce External References
Eliminate unnecessary function calls. For example, the statement:
c = log(a) + log(b)
can be rewritten as:
c = log(a * b)
Also, the statement :
x = y**2
explicitly requires a procedure call to an exponential function
procedure. Rewriting this statement as:
x = y * y
avoids the procedure call.
If a function is called more than once with the same arguments, you can
eliminate the additional procedure calls by assigning the result to a
temporary variable. For example, the statements:
a = MIN(x,y) + 1.0
b = MIN(x,y) + 4.0
can be rewritten as:
minval = MIN(x,y)
a = minval + 1.0
b = minval + 4.0
The rewritten statements above are more efficient, but the readability is
reduced.
Combine DO Loops
Combine adjacent DO loops that are executed the same number of times.
For example, the statements:
DO 100 i = 1,20
100 a(i) = b(i) + c(i)
DO 200 j = 1,20
200 x(j) = y(j) + z(j)
can be replaced with the statements:
DO 100 i = 1,20
a(i) = b(i) + c(i)
x(i) = y(i) + z(i)
100 CONTINUE
Eliminate Short DO Loops
Break short DO loops into separate statements to eliminate the overhead
associated with the loop. For example, the statements:
DO 50 i = 1,3
50 c(i) = a(i) * b(i)
can be replaced with the statements:
c(1) = a(1) * b(1)
c(2) = a(2) * b(2)
c(3) = a(3) * b(3)
However, removing DO loops makes programs longer and is not practical if
the number of loop interations is large.
Eliminate Common Operations in Loops
Minimize operations inside of a loop. If the result of an operation is
the same throughout the loop, move the expression before or after the
loops so the expression is only executed once. For example, the loop:
sum = 0.0
DO 100 i = 1,n
100 sum = sum + value * a(i)
can be replaced with:
sum=0.0
DO 100 i = 1,n
100 sum = sum + a(i)
sum = value * sum
Use Efficient IF Statements
In block IF statements, order the conditions so that the most likely
condition is tested first. For example, if the value of arg is three in
most cases, write a compound IF statement as:
IF (arg .EQ. 3) THEN
.
.
.
ELSE IF (arg .EQ. 1) THEN
.
.
.
ELSE IF (arg .EQ. 2) THEN
.
.
.
ELSE
.
.
.
When using the logical operators .AND. and .OR. in an IF condition, the
code generated only checks enough conditions to determine the result of
the entire logical expression. If several logical expressions are
connected with .OR., checking discontinues as soon as an expression
evaluates to .TRUE.. When .AND. is used, checking discontinues as soon
as a .FALSE. condition is found. Therefore, order the conditions so the
least number of checks is done. For example, if it is more likely that
variable a will equal zero than it is that b will be greater than 100,
write the IF statement as:
IF ((a .EQ. 0) .OR. (b .GT. 100))
or:
IF ((b .GT. 100) .AND. (a .EQ. 0))
Avoid Formatted I/O
When possible, use unformatted I/O. Formatted I/O requires costly
conversions between binary and ASCII format.
When using formatted I/O, put the format string in a separate FORMAT
statement instead of using a variable. For example, use the statements:
WRITE (6,20) var
20 FORMAT (F10.2)
instead of:
CHARACTER*7 a
DATA a/'(F10.2)'/
WRITE (6,a) var
Format specifiers contained in variables are not parsed when a program is
compiled. Instead, a format processing routine is called by the compiled
program each time the format is used.
Specify the Array Name for I/O
When reading or writing an array, specifiy the array name instead of
using an implied DO loop. This allows the array to be operated on as a
whole, instead of performing individual operations for each element. For
example, specify:
WRITE (6, '(A1)') myarray
instead of:
WRITE (6, '(A1)') (myarray(i,j), i=1,10), j=1,10)
Avoid Using Range Checking
Turn range checking on only when necessary. This option causes extra
code to be included in your program to check the bounds when a substring
or array element is referenced. Code is also generated for checking
assigned GOTO statements. This added code causes your program to take
longer to execute, as well as using additional code space.
Use Your System Language
In some cases it might help efficiency to write part of your program in
the system language of your machine. For example, if you have to move an
entire array to another array with the same dimensions, your system
language might allow you to move the array as a single block instead of
moving each array element separately. If the array is large, using the
system language could save a significant amount of execution time.
Minimize Segment Faults
On systems using memory segmenting, segment your program with efficiency
in mind. If a large amount of interaction takes place between two
program units, make sure that the program units are placed in the same
segment. Try to minimize the total number of segments used, without
making any one segment too large.
MPE/iX Run-Time Efficiency Topics
To improve run-time efficiency on the MPE/iX operating system, do the
following:
* When using the CHECK_OVERFLOW compiler directive, specify
$CHECK_OVERFLOW INTEGER OFF
If left in the default state of ON, the directive generates extra
code for each integer assignment for integer overflow checking.
* Use MPE/iX intrinsic I/O instead of the FORTRAN READ and WRITE
statements. The FORTRAN statements generate several procedure
calls for each statement. However, MPE/iX intrinsics make
programs system-dependent and difficult to port.
* When possible, use DO loops instead of DO WHILE loops. The code
generated to evaluate the DO loop counter is more efficient if the
loop counter is type INTEGER*4 and if there are no ASSIGN
statements in the program unit.
* Avoid using common variables, variables initialized by DATA
statements, arrays, equivalenced data, and variables with a length
greater than 64 bits. These structures are addressed indirectly;
that is, their addresses must first be found and then the elements
at those addresses found.
* Avoid using the HP3000_16 compiler directive. Instead, change
equivalence and common data to take advantage of the HP Precision
Architecture, convert files that contain real data to IEEE format,
and modify character assignments if your application takes
advantage of the ripple effect of overlapping character strings.
* Use the LOCALITY compiler directive to strategically place
subroutines and functions in memory.
MPE/iX 5.0 Documentation