HP 3000 Manuals

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