Porting dusty deck Fortran source can be an exercise in patience and conditional compilation. An application that needs to run in the ILP-32, LP-64, and ILP-64 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 ( ILP-32 interface: SUBROUTINE saxpy(N, ALPHA, X, INCX, Y, INCY) INTEGER*4 :: N, INCX, INCY REAL*4 :: ALPHA, X(*), Y(*) LP-64 interface: SUBROUTINE saxpy(N, ALPHA, X, INCX, Y, INCY) INTEGER*4 :: N, INCX, INCY REAL*4 :: ALPHA, X(*), Y(*) ILP-64 interface: SUBROUTINE saxpy(N, ALPHA, X, INCX, Y, INCY) INTEGER*8 :: N, INCX, INCY REAL*4 :: ALPHA, X(*), Y(*) ILP-64 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 The ILP-64 interfaces to the Sun Performance Library routines are suffixed by There are a variety of ways to handle this. First, here's a purely brute-force 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 brute-force 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 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 (ILP-32, LP-64, and ILP-64). Let's take a very simple example that calls the BLAS
% 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=[sparc|sparcvis|sparcvis2|sse2]
% tst
30.0
When compiled with one of the ILP-32 architectures ( % f95 -o tst tst.f -xlic_lib=sunperf -m64 \ -xarch=[sparc|sparcvis|sparcvis2|sse2] % tst 30.0 When compiled with one of the ILP-64 architectures (
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=[sparc|sparcvis|sparcvis2|sse2] -xtypemap=integer:64
% tst
30.0
The integer declarations have been changed to 8-byte integers using the
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=[sparc|sparcvis|sparcvis2|sse2]
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 In the example above, if we forget the An F95 interface can be used to describe the different programming models.
module sunperf64
interface saxpy
!
! ILP-32 and LP-64 interface
!
subroutine saxpy(n,alpha,x,incx,y,incy)
integer(4) :: n, incx, incy
real(4) :: alpha, x(*), y(*)
end subroutine
!
! ILP-64 interface
!
subroutine saxpy_64(n,alpha,x,incx,y,incy)
integer(8) :: n, incx, incy
real(4) :: alpha, x(*), y(*)
end subroutine
!
! ILP-64 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 % f95 -c sunperf64.F95 This will create a F95 Given the original example code, the only source-level change that needs to be
made is the addition of the
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 ILP-32 version: % f95 -o tst tst.f -xlic_lib=sunperf -xarch=[sparc|sparcvis|sparcvis2|sse2] This line would call the LP-64 version: % f95 -o tst tst.f -xlic_lib=sunperf -xarch=[sparc|sparcvis|sparcvis2|sse2] -m64 The following line would call the ILP-64 version: % f95 -o tst tst.f -xlic_lib=sunperf \ -xarch=[sparc|sparcvis|sparcvis2|sse2] -m64 -xtypemap=integer:64 And this line would call the ILP-64 (strict) version: % f95 -o tst tst.f -xlic_lib=sunperf \ -xarch=[v9|v9b|amd64] -xtypemap=integer:64,real:64 -m64 If the above experiments are performed, the compiler will complain that % f90 -c -m32 sunperf64.F90 ** for ILP-32 % f90 -c -m64 sunperf64.F90 ** for LP-64 % f90 -c -m64 sunperf64.F90 -xtypemap=integer:64 ** for ILP-64 About the AuthorPaul 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. | ||||||||
|
| ||||||||||||