
By Paul Hinker, Sun Microsystems, June 2007 

Porting dusty deck Fortran source can be an exercise in patience and conditional compilation. An application that needs to run in the ILP32, LP64, and ILP64 models faces the problem of interfacing with external libraries seamlessly.
Here are examples of using the Basic Linear Algebra Subprogram Standard (BLAS) AXPY family of routines (
caxpy
,
daxpy
,
saxpy
, and
zaxpy
):
ILP32 interface:
SUBROUTINE saxpy(N, ALPHA, X, INCX, Y, INCY) INTEGER*4 :: N, INCX, INCY REAL*4 :: ALPHA, X(*), Y(*)
LP64 interface:
SUBROUTINE saxpy(N, ALPHA, X, INCX, Y, INCY) INTEGER*4 :: N, INCX, INCY REAL*4 :: ALPHA, X(*), Y(*)
ILP64 interface:
SUBROUTINE saxpy(N, ALPHA, X, INCX, Y, INCY) INTEGER*8 :: N, INCX, INCY REAL*4 :: ALPHA, X(*), Y(*)
ILP64 interface (strict Fortran type adherence):
SUBROUTINE saxpy(N, ALPHA, X, INCX, Y, INCY) INTEGER*8 :: N, INCX, INCY REAL*8 :: ALPHA, X(*), Y(*)
Strict Fortran adherence means that
INTEGER
and
REAL
data types have identical bitwidth. This is contrary to the strong implication that single precision routines (i.e., those that are prefixed by '
s
') expect 32bit floating point data. (See
Further Details: Floating Point Arithmetic in the
LAPACK Users' Guide.)
The ILP64 interfaces to the Sun Performance Library routines are suffixed by
_64
to distinguish them from routines by the same name that expect 32bit integers but run in an LP64 model. Some older Cray source code strictly adheres to the Fortran Language specification, which requires
INTEGER
and
REAL
data types to have the same bit width, and that source code expects the floating point data sent to the
s
prefixed routines to be 64bit.
There are a variety of ways to handle this. First, here's a purely bruteforce approach of manually editing the source with conditional compilation code:
#ifdef ILP64 call saxpy_64(n,alpha,incx,y,incy) #else call saxpy(n,alpha,incx,y,incy) #endif
Applying the bruteforce approach to an application that consists of thousands of files and millions of lines of source code is a waste of engineering time. The same effect can be accomplished with an
awk
,
sed
, or
perl
script, but there are 1700+ routines in the Performance Library, so even scripting the process would be time consuming and error prone.
Another option is to use the Fortran 95 generic interface functionality to allow the source code to remain virtually unchanged and yet facilitate the use of each of the three programming models (ILP32, LP64, and ILP64).
Let's take a very simple example that calls the BLAS
saxpy
routine:
% cat tst.f program tst saxpy implicit none integer, parameter :: N = 10, INCX = 1, INCY = 1 real, parameter :: ALPHA = 1.0 real, dimension(N) :: X, Y X = 1.0 Y = 2.0 call saxpy_64(N, ALPHA, X, INCX, Y, INCY) print *, SUM(Y) END % f95 o tst tst.f xlic_lib=sunperf m32 \ xarch=[sparcsparcvissparcvis2sse2] % tst 30.0
When compiled with one of the ILP32 architectures (
m32
), the
saxpy
call resolves to the one expecting 32bit integers and real parameters.
% f95 o tst tst.f xlic_lib=sunperf m64 \ xarch=[sparcsparcvissparcvis2sse2] % tst 30.0
When compiled with one of the ILP64 architectures (
m64
), the
saxpy
call resolves to the LP64 interface, which expects 32bit integers and real parameters. This behavior is for backward compatibility reasons. However, when compiled with one of the ILP64 libraries, additional entry points are available. That is, our source could look like the following:
program tst saxpy implicit none integer, parameter :: N = 10, INCX = 1, INCY = 1 real, parameter :: ALPHA = 1.0 real, dimension(N) :: X, Y X = 1.0 Y = 2.0 call saxpy_64(N, ALPHA, X, INCX, Y, INCY) print *, SUM(Y) END % f95 o tst tst.f xlic_lib=sunperf m64 \ xarch=[sparcsparcvissparcvis2sse2] xtypemap=integer:64 % tst 30.0
The integer declarations have been changed to 8byte integers using the
xtypemap
compiler option. Explicit declaration changes could be made in the source itself.
program tst saxpy implicit none integer(8), parameter:: N = a10, INCX = 1, INCY = 1 real, parameter :: ALPHA = 1.0 real, dimension(N) :: X, Y X = 1.0 Y = 2.0 call saxpy_64(N, ALPHA, X, INCX, Y, INCY) print *, SUM(Y) END % f95 o tst tst.f xlic_lib=sunperf m64 \ xarch=[sparcsparcvissparcvis2sse2] Warning : The xtypemap option only applies to implicitly typed variables. INTEGER :: N gets promoted to INTEGER*8 :: N but INTEGER*4 :: N would not be promoted.
In theory, the
xtypemap
option is a great way to port to the ILP64 model. In practice, it's not quite a silver bullet. As long as interfaces are clearly defined and strictly follow typing rules, it works well.
In the example above, if we forget the
xtypemap=integer:64
flag on the compilation line and do not explicitly change the integers passed to the
saxpy_64
routine to
INTEGER*8
, the compiler will generate no errors or warnings (since Fortran doesn't do type matching). But when the program is run, chances are the results will be wrong or a segmentation fault will occur, since 32bit integers will be sent to a routine that is expecting 64bit integers.
An F95 interface can be used to describe the different programming models.
module sunperf64 interface saxpy ! ! ILP32 and LP64 interface ! subroutine saxpy(n,alpha,x,incx,y,incy) integer(4) :: n, incx, incy real(4) :: alpha, x(*), y(*) end subroutine ! ! ILP64 interface ! subroutine saxpy_64(n,alpha,x,incx,y,incy) integer(8) :: n, incx, incy real(4) :: alpha, x(*), y(*) end subroutine ! ! ILP64 interface w/strict Fortran typing ! subroutine daxpy_64(n,alpha,x,incx,y,incy) integer(8) :: n, incx, incy real(8) :: alpha, x(*), y(*) end subroutine end interface end module
If this module is compiled into a
.mod
file, it will allow a single call to the
saxpy
routine to be interpreted as any of the ILP32, LP64, ILP64, or ILP64 (strict) calling conventions.
% f95 c sunperf64.F95
This will create a
.mod
file in the current directory by the name of
sunperf64.mod
. It will also create a
sunperf64.o
file (which contains nothing of use and can be discarded).
F95
.mod
files provide the F95 compiler with information concerning interfaces to subroutines and functions. These files allow the compiler to check subroutine and function call parameter lists for type, number, and shape consistency.
Given the original example code, the only sourcelevel change that needs to be made is the addition of the
USE SUNPERF64
statement at the beginning of the program, subroutine, or function that calls Performance Library routines. Of course, you can call the module file anything you like.
program tst saxpy use sunperf64 implicit none integer, parameter :: N = 10, INCX = 1, INCY = 1 real, parameter :: ALPHA = 1.0 real, dimension(N) :: X, Y X = 1.0 Y = 2.0 call saxpy_64(N, ALPHA, X, INCX, Y, INCY) print *, SUM(Y) END
Then, this line would call the ILP32 version:
% f95 o tst tst.f xlic_lib=sunperf xarch=[sparcsparcvissparcvis2sse2]
This line would call the LP64 version:
% f95 o tst tst.f xlic_lib=sunperf xarch=[sparcsparcvissparcvis2sse2] m64
The following line would call the ILP64 version:
% f95 o tst tst.f xlic_lib=sunperf \ xarch=[sparcsparcvissparcvis2sse2] m64 xtypemap=integer:64
And this line would call the ILP64 (strict) version:
% f95 o tst tst.f xlic_lib=sunperf \ xarch=[v9v9bamd64] xtypemap=integer:64,real:64 m64
If the above experiments are performed, the compiler will complain that
sunperf64.mod
was compiled with a different default integer type, a different architecture than the executable that is being created, or both. Since there is no executable code in the interfaces created by the
.mod
file, these warnings are harmless. If the warnings are bothersome, the
.mod
file can be created in several different incarnations:
% f90 c m32 sunperf64.F90 ** for ILP32 % f90 c m64 sunperf64.F90 ** for LP64 % f90 c m64 sunperf64.F90 xtypemap=integer:64 ** for ILP64
Paul Hinker has worked in the Performance Library Group for 10 years as the Team Lead and Technical Lead. Before coming to Sun as part of the acquisition of Dakota Scientific Software, Paul worked in the Advanced Computing Laboratory at the Los Alamos National Laboratory. The Performance Library Group is based in Broomfield, Colorado and produces the Sun Performance Library (a.k.a. Perflib or Sunperf), which is part of the Sun Studio Compiler and Tools package.