John K. Prentice
Quetzal Computational Associates
quetzal@aip.org
With the adoption of Fortran 90 as an ANSI/ISO standard, support for Fortran 77 compilers will slowly cease, just as happened with Fortran 66 compilers during the 1980's. While Fortran 77 codes can be compiled with Fortran 90 compilers, the Fortran 90 standard requires that Fortran 77 codes compile with a standard conforming Fortran 90 compiler, it seems likely that the bulk of the effort in developing optimization techniques for Fortran in the future will be concentrated in optimizing of the newer features of Fortran 90 such as array syntax. For those using high performance computers, the situation is even more pressing. Fortran 77 codes are not easily adapted to modern high performance computers, particularly massively parallel systems. The reasons for this are varied, but one of the most significant is that neither of these earlier languages provided any straightforward way to express parallelism. Fortran 90 does have features which assist in the expression of data parallelism and these features form the kernel of both the CM-Fortran language for the Connection Machine and the more widely applicable High Performance Fortran language. In addition, the use of features such as Fortran 90 array syntax forces programmers to consider issues that are important to parallelism, such as data dependence in loops.
Fortran 90 compilers are now commercially available from the Numerical Algorithms Group (NAG), Pacific-Sierra Research, and ParaSoft. In addition, Edinburgh Portable Compilers, Lahey, SunPro, Cray, and many other companies have compilers under development which will become available over the next year or so. The Connection Machines, the CM-2 and CM-5, use a dialect of Fortran which incorporates some of features of Fortran 90, and there are several universities and companies actively working to produce compilers for High Performance Fortran that add explicit parallelism constructs to Fortran 90. With all this activity by compiler developers, it is clearly a good time to begin migrating old codes to Fortran 90 and to start writing any new codes in it. Certainly for anyone interested in high performance computing, it makes very little sense to be doing Fortran programming in anything but Fortran 90. The difficulty however is that conversion of older Fortran codes to Fortran 90, if done by hand, can be a very time intensive process and consequently an extremely expensive one.
What makes the migration of old codes complicated is that the syntax of good Fortran 90 programs is entirely different than earlier Fortran and many of the features of Fortran 90 that make it especially valuable for high performance computing are completely new and require at least some amount of code restructuring. Clearly, tools are needed to assist in this process and several have been written to at least transform the syntax of Fortran 77 codes to Fortran 90. Pacific-Sierra Research has produced a tool which goes much further however. Their VAST-90 code is an extremely powerful tool for migrating Fortran 77 to Fortran 90, going far beyond a simple translation of the syntax. Using VAST-90, I have been able to migrate literally tens of thousands of lines of Fortran 77 to Fortran 90 in an extremely short amount of time. This article discusses some features of VAST-90 and gives some examples of how it works in practice.
The process of translating Fortran 77 to Fortran 90 with VAST-90 is surprisingly fast. For example, I recently ran VAST-90 to translate a code containing 8001 lines of Fortran 77, involving 85 individual routines. Using the default translation options, VAST-90 performed the Fortran 77 to Fortran 90 conversion in 14.0 seconds on a Sparc 10, including generating interface files and modules. Using the option to aggressively generate array syntax, the translation required 20.7 seconds.
The translation technology in VAST-90 is an outgrowth of much of the work Pacific-Sierra Research has done over the years in building optimization tools for supercomputers. For example, many of the optimization and vectorization tools used by Cray Research as part of their CF77 Compiling System were developed by Pacific-Sierra Research. Their considerable experience with this technology may account for the maturity of the Fortran 77 to Fortran 90 translation capability of VAST-90 and the fact that every Fortran 77 to Fortran 90 translation I have performed with VAST-90 has been error free.
In the course of developing Fortran 90 codes for the purpose of benchmarking Fortran 90 compilers, I have used VAST-90 to convert literally tens of thousands of lines of Fortran 77 code. In general, I run VAST-90 to make an initial conversion to Fortran 90 and then go in and make additional changes to further optimize the code. While VAST-90 can be used to perform the complete conversion, my general feeling is that it is best regarded as a tool that does about 90% of the work in migrating a code from Fortran 77 to Fortran 90. The remaining 10% of the migration must often be done by the programmer and involves improving VAST-90's translation. The Quetzal Fortran 90 Benchmark Suite has several codes which were converted from Fortran 77 to Fortran 90 in this fashion, for example, the gas dynamics and overlap codes (this benchmark suite is available via anonymous ftp from unmfys.unm.edu. Log in as anonymous. The benchmark suite is in the directory pub/quetzal. There is a copy of the most recent benchmark report in that directory also. The report discusses each of the benchmarks and gives execution times for code generated with different Fortran 90 compilers.).
SUBROUTINE BCF2AD(IBOUND,HOLD,BOT,WETDRY,IWDFLG,ISS,
1 NCOL,NROW,NLAY)
DIMENSION IBOUND(NCOL,NROW,NLAY),HOLD(NCOL,NROW,NLAY),
1 BOT(NCOL,NROW,NLAY),WETDRY(NCOL,NROW,NLAY)
COMMON /FLWCOM/LAYCON(80)
IF(IWDFLG.EQ.0 .OR. ISS.NE.0) RETURN
KB=0
DO 100 K=1,NLAY
KB=KB+1
DO 90 I=1,NROW
DO 90 J=1,NCOL
IF(IBOUND(J,I,K).NE.0) GO TO 90
IF(WETDRY(J,I,KB).EQ.0.) GO TO 90
HOLD(J,I,K)=BOT(J,I,KB)
90 CONTINUE
100 CONTINUE
RETURN
END
This is a simple and short routine, but one that has some
curious features. The use of the KB variable, for example, is
superfluous. The IF checks in the inner loop could be condensed also.
On my first try, I ran VAST-90 with the default options. The result
was:
SUBROUTINE BCF2AD(IBOUND, HOLD, BOT, WETDRY, IWDFLG, ISS, NCOL, &
& NROW, NLAY)
!...Translated by Pacific-Sierra Research VAST-90 1.02M 17:22:14 7/29/93
!...Switches:
!-----------------------------------------------
! M o d u l e s
!-----------------------------------------------
USE VFLWCOM
IMPLICIT NONE
!-----------------------------------------------
! D u m m y A r g u m e n t s
!-----------------------------------------------
INTEGER IWDFLG, ISS, NCOL, NROW, NLAY
INTEGER, DIMENSION(NCOL,NROW,NLAY) :: IBOUND
REAL, DIMENSION(NCOL,NROW,NLAY) :: HOLD, BOT, WETDRY
!-----------------------------------------------
! L o c a l V a r i a b l e s
!-----------------------------------------------
INTEGER :: KB, K, I, J
!-----------------------------------------------
IF (IWDFLG==0 .OR. ISS/=0) RETURN
KB = 0
WHERE (IBOUND==0 .AND. WETDRY(:,:,KB+1:NLAY+KB)/=0.) HOLD = BOT(:,&
& :,KB+1:NLAY+KB)
RETURN
END SUBROUTINE BCF2AD
Note that VAST-90 has converted the source form to Fortran 90
free source form, including changing the comments from the Fortran 77
form to the Fortran 90 form. In addition, the FLWCOM labeled common
block in the original Fortran 77 code has been automatically converted
to a module, the declaration of variables has been changed to the
Fortran 90 form, and VAST-90 has grouped the declarations by whether
they are in modules, they are dummy arguments, or they are local
variables. The superfluous KB variable is still present (you can't have
everything!), but VAST-90 has correctly recognized that incrementing it
in the outer loop is not necessary. In fact, there is no outer loop
anymore, nor any inner loops. VAST-90 has collapsed the three nested
loops in the original Fortran 90 into a single statement employing array
syntax, using the WHERE construct to handle the cases where the
assignment should be skipped.
The next routine I converted was SBCF1C:
SUBROUTINE SBCF1C(CR,CC,TRPY,DELR,DELC,K,NCOL,NROW,NLAY)
DIMENSION CR(NCOL,NROW,NLAY), CC(NCOL,NROW,NLAY)
2 , TRPY(NLAY), DELR(NCOL), DELC(NROW)
YX=TRPY(K)*2.
DO 40 I=1,NROW
DO 40 J=1,NCOL
T1=CC(J,I,K)
IF(T1.NE.0.) GO TO 10
CR(J,I,K)=0.
GO TO 40
10 IF(J.EQ.NCOL) GO TO 30
T2=CC(J+1,I,K)
CR(J,I,K)=2.*T2*T1*DELC(I)/(T1*DELR(J+1)+T2*DELR(J))
30 IF(I.EQ.NROW) GO TO 40
T2=CC(J,I+1,K)
CC(J,I,K)=YX*T2*T1*DELR(J)/(T1*DELC(I+1)+T2*DELC(I))
40 CONTINUE
RETURN
END
This routine is interesting because the use of the GOTO statements
has generated some classic Fortran spaghetti code. Running
this routine through VAST-90 with the default options produced
the following:
SUBROUTINE SBCF1C(CR, CC, TRPY, DELR, DELC, K, NCOL, NROW, NLAY)
!...Translated by Pacific-Sierra Research VAST-90 1.02M 17:29:59 7/29/93
!...Switches:
IMPLICIT NONE
!-----------------------------------------------
! D u m m y A r g u m e n t s
!-----------------------------------------------
INTEGER K, NCOL, NROW, NLAY
REAL, DIMENSION(NCOL,NROW,NLAY) :: CR, CC
REAL, DIMENSION(NLAY) :: TRPY
REAL, DIMENSION(NCOL) :: DELR
REAL, DIMENSION(NROW) :: DELC
!-----------------------------------------------
! L o c a l V a r i a b l e s
!-----------------------------------------------
INTEGER :: I, J
REAL :: YX, T1, T2
!-----------------------------------------------
YX = TRPY(K)*2.
DO I = 1, NROW
DO J = 1, NCOL
T1 = CC(J,I,K)
IF (T1 /= 0.) GO TO 10
CR(J,I,K) = 0.
CYCLE
10 CONTINUE
IF (J /= NCOL) THEN
T2 = CC(J+1,I,K)
CR(J,I,K) = 2.*T2*T1*DELC(I)/(T1*DELR(J+1)+T2*DELR(J))
ENDIF
IF (I == NROW) CYCLE
T2 = CC(J,I+1,K)
CC(J,I,K) = YX*T2*T1*DELR(J)/(T1*DELC(I+1)+T2*DELC(I))
END DO
END DO
RETURN
END SUBROUTINE SBCF1C
VAST-90 replaced most of the GOTO's with a IF-THEN-ELSE
construct and indented the code so as to make it much more readable.
VAST-90 has also added a CYCLE command just before the line with
statement label 10. The purpose of the CYCLE command is to
skip to the end of the inner loop instead of continuing on to
the next executable statement. Note that the remaining GOTO
could have been eliminated in this routine, but this version is
still clearly an improvement over the original Fortran 77!
VAST-90 also automatically generated an interface file for this routine. Fortran 90 interface files allow the compiler to catch discrepancies in the number and type of dummy arguments, as well as in the dimension of arrays. An option exists in VAST-90 to automatically generate interface files for a subroutine, as well as to automatically include interface files for subroutines or functions called by a routine. The interface file VAST-90 generated for subroutine SBCF1C was:
INTERFACE
SUBROUTINE SBCF1C (CR, CC, TRPY, DELR, DELC, K, NCOL, NROW, NLAY)
!...Generated by Pacific-Sierra Research VAST-90 1.02M 17:28:40 7/29/93
REAL, DIMENSION(NCOL,NROW,NLAY), INTENT(OUT) :: CR
REAL, DIMENSION(NCOL,NROW,NLAY), INTENT(INOUT) :: CC
REAL, DIMENSION(NLAY), INTENT(IN) :: TRPY
REAL, DIMENSION(NCOL), INTENT(IN) :: DELR
REAL, DIMENSION(NROW), INTENT(IN) :: DELC
INTEGER, INTENT(IN) :: K
INTEGER, INTENT(IN) :: NCOL
INTEGER, INTENT(IN) :: NROW
INTEGER, INTENT(IN) :: NLAY
END SUBROUTINE
END INTERFACE
By including this interface file in any routines that call SBCF1C, I
can now be assured that the dimension of the arrays passed as dummy
arguments is consistent throughout the code. Further, note that VAST-90
determined the INTENT of the various dummy arguments. In this case,
the input values of the CR array are not used by this routine, but the
array values are changed in it. Hence, the INTENT for this routine is
OUT. By contrast, the values passed into the routine for CC are both
used by the routine and then modified, making the INTENT of this array
INOUT. The values passed to this routine for all of the other dummy
arguments are used by the routine but not modified, thus their INTENT
is IN. Declaring the INTENT of dummy arguments in this way allows for
the compiler to optimize the code in ways that are impossible with
earlier versions of Fortran.
Next I turned on the VAST-90 option to aggressively generate array syntax. No array syntax was generated during the earlier translation because doing so would lead to code which is difficult to read. By turning on the option to aggressively generate array syntax, I have instructed VAST-90 to generate array syntax whenever possible, irrespective of how complicated or difficult it is to read. The file it generated was:
SUBROUTINE SBCF1C(CR, CC, TRPY, DELR, DELC, K, NCOL, NROW, NLAY)
!...Translated by Pacific-Sierra Research VAST-90 1.02P 12:47:33 8/05/93
!...Switches: -xr
IMPLICIT NONE
!-----------------------------------------------
! D u m m y A r g u m e n t s
!-----------------------------------------------
INTEGER K, NCOL, NROW, NLAY
REAL, DIMENSION(NCOL,NROW,NLAY) :: CR, CC
REAL, DIMENSION(NLAY) :: TRPY
REAL, DIMENSION(NCOL) :: DELR
REAL, DIMENSION(NROW) :: DELC
!-----------------------------------------------
! L o c a l V a r i a b l e s
!-----------------------------------------------
INTEGER :: I, J, J1
REAL :: YX, T1, T2
REAL , ALLOCATABLE :: T11U(:)
LOGICAL , ALLOCATABLE :: L1V(:)
!-----------------------------------------------
YX = TRPY(K)*2.
DO I = 1, NROW
IF (I == NROW) THEN
ALLOCATE (T11U(NCOL), L1V(NCOL))
L1V = .FALSE.
T11U = CC(:,I,K)
WHERE (T11U == 0.)
CR(:,I,K) = 0.
ELSEWHERE
L1V = (/(J1,J1=1,NCOL)/) /= NCOL
END WHERE
WHERE (L1V) CR(:,I,K) = 2.*CC(2:NCOL+1,I,K)*T11U*DELC(I)/( &
& T11U*DELR(2:NCOL+1)+CC(2:NCOL+1,I,K)*DELR)
DEALLOCATE (T11U, L1V)
ELSE
DO J = 1, NCOL
T1 = CC(J,I,K)
IF (T1 /= 0.) GO TO 1053
CR(J,I,K) = 0.
CYCLE
1053 CONTINUE
IF (J /= NCOL) THEN
T2 = CC(J+1,I,K)
CR(J,I,K) = 2.*T2*T1*DELC(I)/(T1*DELR(J+1)+T2*DELR(J))
ENDIF
T2 = CC(J,I+1,K)
CC(J,I,K) = YX*T2*T1*DELR(J)/(T1*DELC(I+1)+T2*DELC(I))
END DO
ENDIF
END DO
RETURN
END SUBROUTINE SBCF1C
As advertised, the aggressive array syntax option has produced
a considerably more complicated Fortran 90 version than that produced
with the default VAST-90 option. Out of curiosity, I added a driver
to these two Fortran 90 versions of SBCF1C and ran them on a Sparc 10.
Using both VAST-90 and the NAG Fortran 90 compilers, the execution
time for both versions was nearly identical. So, on this scalar RISC
computer, the aggressive array syntax option neither helped
nor hurt the execution speed. On a vector or parallel computer
it is possible that the version generated with the aggressive
array syntax option would be faster. If the use of array syntax is
not a significant issue on your computer, however, the default
translation is obviously easier to read and would therefore be
preferable. In this particular case, it is also possible to hand
translate this routine into a form that uses array syntax, but is much
cleaner than what VAST-90 has produced here. This underscores my
earlier point that some amount of effort on the part of the programmer
is still required to achieve the optimal translation of codes from
Fortran 77 to Fortran 90.
Pacific-Sierra Research Corporation Computer Products Group 2901 28th Street, Suite 300 Santa Monica, CA 90405 USA
phone: (310) 314-2300 FAX: (310) 314-2323 e-mail: info@psrv.com

21. Aug 1997
Wilhelm
Gehrke
gehrke@rrzn.uni-hannover.de