Fortran Arguments Passing Test Sets http://ftp.aset.psu.edu/pub/ger/fortran/test/FortranArgPassing/results.txt Arnaud Desitter: http://www.geog.ox.ac.uk/staff/adesitter.html Oxford University School of Geography and the Environment Herman D. Knoble: http://www.personal.psu.edu/hdk/ Penn State Academic Services and Emerging Technologies 20 June 2007 INTRODUCTION The test below measures the penalty incurred when a Pointer array in a derived Type is passed to a routine using assumed sized array, assumed shape array or derived types as dummy arguments. 1990s Fortran compilers used to generate poor code in such situations, most notably by generating systematic temporary copies of arrays irrespectively of their actual contiguity ("copy in/copy out"). The situation has improved as the results below show despite a few remaining problems. Fortran 2003 allows Allocatable arrays in derived types. Unlike Pointer arrays, Allocatable arrays are always contiguous and cannot alias each other. Therefore, temporaries are never necessary if they are produced to ensure contiguity or to avoid aliasing. Additionally, we test the use of array notation versus Do loop for a very simple case (A=2*B). It may itself be a source of penalty although current compilers should not have any problems with such a simple case. Note that non-aliasing rules of dummy arguments does not apply to Pointer arrays contained in derived type dummy arguments. It does make it hard to produce "good" code in that case. In practice, the problem can be easily avoided by passing the pointer components to an auxiliary routine with adequate dummy arguments so that the aliasing rule can be exploited. The case "Derived type pointer + Derived type" below illustrates this point. The two derived types used are, respectively: ! Derived type pointer Type T_OBJ Double Precision, Pointer, Dimension(:,:)::R End Type T_OBJ ! Derived type allocatable Type T_OBJ Double Precision, Allocatable, Dimension(:,:)::R End Type T_OBJ The routines called are: ! assumed size Subroutine OV(X,Y,N1,N2) Integer, Intent(IN) :: N1,N2 Double Precision, Intent(IN) :: Y(N1,N2) Double Precision, Intent(INOUT) :: X(N1,N2) ! assumed shape 1 Subroutine OV_SH1(X,Y) Double Precision, Intent(IN) :: Y(:,:) Double Precision, Intent(INOUT) :: X(:,:) ! assumed shape 2 Subroutine OV_SH2(X,Y) Double Precision, Intent(IN) :: Y(:) Double Precision, Intent(INOUT) :: X(Size(Y,1),Size(Y,2)) ! derived type Subroutine OV_DT(X,Y) Type(T_OBJ), Intent(IN) :: Y Type(T_OBJ), Intent(INOUT) :: X Other related links can be found at: Michel Olagnon's Fortran 90 List http://www.ifremer.fr/ditigo/molagnon/fortran90/engfaq.html#2.4 SOURCE CODE The source code is composed of: tdefa.f90 tdefp.f90 tlib.f90 tliba.f90 tlibp.f90 ttesta.f90 ttestp.f90 STRUCTURE OF THE TESTS There are two tests at present. "testp" tests a pointer array in a derived type. "testa" tests an allocatable array in a derived type. The latter is part of Fortran 2003 and may not be supported by all compilers. The typical build/run sequence on Unix is: (testp) f95 -O -c tlib.f90; f95 -O -c tdefp.f90; f95 -O -c tlibp.f90 ar cr tlib.a tlib.o tdefp.o tlibp.o; f95 -O -c ttestp.f90; f95 -O -o ttest ttestp.o tlib.a; ./ttest (testa) f95 -O -c tlib.f90; f95 -O -c tdefa.f90; f95 -O -c tliba.f90 ar cr tlib.a tlib.o tdefa.o tliba.o; f95 -O -c ttesta.f90; f95 -O -o ttest ttesta.o tlib.a; ./ttest We use a static archive to follow production system practice and avoid artificial optimisation that may occur if everything is packed in a single file. Results should be accurate within a few percents (typically 2%). RESULTS ------------------------------------------------------------------------------- Intel compiler Version 7.1 (Build 20040309Z), Linux x86 Note: the Intel compiler 7.x is superseded. Build options (testp) ifc -O2 -c tlib.f90; ifc -O2 -c tdefp.f90; ifc -O2 -c tlibp.f90; ar cr tlib.a tlib.o tdefp.o tlibp.o; ifc -O2 -c ttestp.f90; ifc -O2 ttestp.o tlib.a; (testa) Not supported. testp Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type pointer + assumed size : 0.99 Regular array + assumed shape 1 : 1.03 Derived type pointer + assumed shape 1 : 1.02 Regular array + assumed shape 2 : 1.01 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 1.00 Using array notation Regular array + assumed size : 1.00 Derived type pointer + assumed size : 0.99 Regular array + assumed shape 1 : 1.03 Derived type pointer + assumed shape 1 : 1.03 Regular array + assumed shape 2 : 1.01 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 2.62 testa Not Supported ------------------------------------------------------------------------------- Intel compiler Version 8.1.018 (Build 20041019Z), Linux x86 Build options (testp) ifort -O2 -c tlib.f90; ifort -O2 -c tdefp.f90; ifort -O2 -c tlibp.f90 ar cr tlib.a tlib.o tdefp.o tlibp.o; ifort -O2 -c ttestp.f90; ifort -O2 ttestp.o tlib.a; (testa) ifort -O2 -c tlib.f90; ifort -O2 -c tdefa.f90; ifort -O2 -c tliba.f90 ar cr tlib.a tlib.o tdefa.o tliba.o; ifort -O2 -c ttesta.f90; ifort -O2 ttesta.o tlib.a; testp Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type pointer + assumed size : 1.00 Regular array + assumed shape 1 : 1.02 Derived type pointer + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 1.01 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 1.14 Using array notation Regular array + assumed size : 1.00 Derived type pointer + assumed size : 0.99 Regular array + assumed shape 1 : 1.01 Derived type pointer + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 1.00 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 1.34 testa Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.01 Derived type allocatable + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 1.01 Derived type allocatable + assumed shape 2 : 1.01 Derived type allocatable + Derived type : 1.10 Using array notation Regular array + assumed size : 1.00 Derived type allocatable + assumed size : 0.99 Regular array + assumed shape 1 : 1.01 Derived type allocatable + assumed shape 1 : 1.01 Regular array + assumed shape 2 : 1.00 Derived type allocatable + assumed shape 2 : 1.00 Derived type allocatable + Derived type : 1.16 ------------------------------------------------------------------------------- Intel compiler for 32-bit applications, Version 9.0.027 (Build 20050912Z), Linux x86 Build options (testp) ifort -O2 -c tlib.f90; ifort -O2 -c tdefp.f90; ifort -O2 -c tlibp.f90 ar cr tlib.a tlib.o tdefp.o tlibp.o; ifort -O2 -c ttestp.f90; ifort -O2 ttestp.o tlib.a; (testa) ifort -O2 -c tlib.f90; ifort -O2 -c tdefa.f90; ifort -O2 -c tliba.f90 ar cr tlib.a tlib.o tdefa.o tliba.o; ifort -O2 -c ttesta.f90; ifort -O2 ttesta.o tlib.a; testp Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type pointer + assumed size : 0.99 Regular array + assumed shape 1 : 1.02 Derived type pointer + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 1.01 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 1.56 Using array notation Regular array + assumed size : 1.00 Derived type pointer + assumed size : 0.99 Regular array + assumed shape 1 : 1.00 Derived type pointer + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 1.02 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 2.01 testa Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type allocatable + assumed size : 1.01 Regular array + assumed shape 1 : 1.01 Derived type allocatable + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 0.99 Derived type allocatable + assumed shape 2 : 0.99 Derived type allocatable + Derived type : 1.30 Using array notation Regular array + assumed size : 0.99 Derived type allocatable + assumed size : 1.01 Regular array + assumed shape 1 : 1.01 Derived type allocatable + assumed shape 1 : 1.01 Regular array + assumed shape 2 : 1.00 Derived type allocatable + assumed shape 2 : 0.99 Derived type allocatable + Derived type : 1.53 ------------------------------------------------------------------------------- Intel(R) Fortran Compiler for Intel(R) EM64T-based applications, Version 9.1.032 Build 20060323. Build options (testp) ifort -O2 -c tlib.f90; ifort -O2 -c tdefp.f90; ifort -O2 -c tlibp.f90 ar cr tlib.a tlib.o tdefp.o tlibp.o; ifort -O2 -c ttestp.f90; ifort -O2 ttestp.o tlib.a; (testa) ifort -O2 -c tlib.f90; ifort -O2 -c tdefa.f90; ifort -O2 -c tliba.f90 ar cr tlib.a tlib.o tdefa.o tliba.o; ifort -O2 -c ttesta.f90; ifort -O2 ttesta.o tlib.a; testp Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type pointer + assumed size : 1.01 Regular array + assumed shape 1 : 0.99 Derived type pointer + assumed shape 1 : 0.99 Regular array + assumed shape 2 : 0.99 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 0.99 Using array notation Regular array + assumed size : 0.99 Derived type pointer + assumed size : 0.99 Regular array + assumed shape 1 : 0.99 Derived type pointer + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 0.99 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 1.00 testa Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.00 Derived type allocatable + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 0.99 Derived type allocatable + assumed shape 2 : 0.99 Derived type allocatable + Derived type : 1.00 Using array notation Regular array + assumed size : 1.00 Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 0.99 Derived type allocatable + assumed shape 1 : 0.99 Regular array + assumed shape 2 : 1.00 Derived type allocatable + assumed shape 2 : 1.01 Derived type allocatable + Derived type : 1.01 ------------------------------------------------------------------------------- NAGWare Fortran 95 compiler Release 5.0(375), Linux x86 Build options (testp) f95 -O3 -c tlib.f90; f95 -O3 -c tdefp.f90; f95 -O3 -c tlibp.f90; ar cr tlib.a tlib.o tdefp.o tlibp.o; f95 -O3 -c ttestp.f90; f95 -O3 ttestp.o tlib.a; (testa) f95 -O3 -c tlib.f90; f95 -O3 -c tdefa.f90; f95 -O3 -c tliba.f90; ar cr tlib.a tlib.o tdefa.o tliba.o; f95 -O3 -c ttesta.f90; f95 -O3 ttesta.o tlib.a; testp Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type pointer + assumed size : 0.99 Regular array + assumed shape 1 : 1.01 Derived type pointer + assumed shape 1 : 0.99 Regular array + assumed shape 2 : 1.00 Derived type pointer + assumed shape 2 : 0.99 Derived type pointer + Derived type : 0.99 Using array notation Regular array + assumed size : 1.00 Derived type pointer + assumed size : 0.99 Regular array + assumed shape 1 : 1.00 Derived type pointer + assumed shape 1 : 0.99 Regular array + assumed shape 2 : 1.00 Derived type pointer + assumed shape 2 : 0.99 Derived type pointer + Derived type : 2.00 testa Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.00 Derived type allocatable + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 1.00 Derived type allocatable + assumed shape 2 : 1.00 Derived type allocatable + Derived type : 1.00 Using array notation Regular array + assumed size : 1.00 Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.00 Derived type allocatable + assumed shape 1 : 1.00 Regular array + assumed shape 2 : 1.00 Derived type allocatable + assumed shape 2 : 1.00 Derived type allocatable + Derived type : 1.01 ------------------------------------------------------------------------------- Salford Compiler FTN95 Version 4.8.0, Windows Build options (testp) ftn95 /optimize tdefp.f90 ftn95 /optimize tlib.f90 ftn95 /optimize tlibp.f90 slim tlib.obj tdefp.obj tlibp.obj /file:tlib ftn95 /optimize ttestp.f90 slink ttestp.obj tlib.lib (testa) Not supported. testp Abstraction penalty versus regular array + assumed size dummy argument + do lo (1 means no penalty) Using Do loop Derived type pointer + assumed size : 1.00 Regular array + assumed shape 1 : 0.83 Derived type pointer + assumed shape 1 : 3.17 Regular array + assumed shape 2 : 0.94 Derived type pointer + assumed shape 2 : 1.84 Derived type pointer + Derived type : 1.40 Using array notation Regular array + assumed size : 0.65 Derived type pointer + assumed size : 0.65 Regular array + assumed shape 1 : 0.65 Derived type pointer + assumed shape 1 : 2.96 Regular array + assumed shape 2 : 0.65 Derived type pointer + assumed shape 2 : 1.80 Derived type pointer + Derived type : 1.18 testa Not supported. ------------------------------------------------------------------------------- Lahey Compiler LF95 Version 7.10.01, Windows Build options (testp) lf95 -tp -o1 -c tdefp.f90 lf95 -tp -o1 -c tlib.f90 lf95 -tp -o1 -c tlibp.f90 lf95 tlib.obj tdefp.obj tlibp.obj -out tlib.lib lf95 -tp -o1 -c ttestp.f90 lf95 ttestp.obj tlib.lib (testa) lf95 -tp -o1 -c tdefa.f90 lf95 -tp -o1 -c tlib.f90 lf95 -tp -o1 -c tliba.f90 lf95 tlib.obj tdefa.obj tliba.obj -out tlib.lib lf95 -tp -o1 -c ttesta.f90 lf95 ttesta.obj tlib.lib testp Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type pointer + assumed size : 3.02 Regular array + assumed shape 1 : 1.12 Derived type pointer + assumed shape 1 : 1.10 Regular array + assumed shape 2 : 1.11 Derived type pointer + assumed shape 2 : 3.21 Derived type pointer + Derived type : 0.92 Using array notation Regular array + assumed size : 0.98 Derived type pointer + assumed size : 3.01 Regular array + assumed shape 1 : 1.12 Derived type pointer + assumed shape 1 : 1.10 Regular array + assumed shape 2 : 1.11 Derived type pointer + assumed shape 2 : 3.21 Derived type pointer + Derived type : 2.02 testa Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.14 Derived type allocatable + assumed shape 1 : 1.14 Regular array + assumed shape 2 : 1.13 Derived type allocatable + assumed shape 2 : 1.13 Derived type allocatable + Derived type : 1.03 Using array notation Regular array + assumed size : 1.00 Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.14 Derived type allocatable + assumed shape 1 : 1.14 Regular array + assumed shape 2 : 1.13 Derived type allocatable + assumed shape 2 : 1.13 Derived type allocatable + Derived type : 1.02 ------------------------------------------------------------------------------- CVF Compiler DF Version 6.6C, Windows Build options (testp) df tdefp.f90 /fast /arch:p6 /optimize:3 /nolink df tlib.f90 /fast /arch:p6 /optimize:3 /nolink df tlibp.f90 /fast /arch:p6 /optimize:3 /nolink lib /name:tlib tlib.obj tdefp.obj tlibp.obj df ttestp.f90 /fast /arch:p6 /optimize:3 /nolink link ttestp.obj tlib.lib (testa) df tdefa.f90 /fast /arch:p6 /optimize:3 /nolink df tlib.f90 /fast /arch:p6 /optimize:3 /nolink df tliba.f90 /fast /arch:p6 /optimize:3 /nolink lib /name:tlib tlib.obj tdefa.obj tliba.obj df ttesta.f90 /fast /arch:p6 /optimize:3 /nolink link ttesta.obj tlib.lib testp Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type pointer + assumed size : 1.00 Regular array + assumed shape 1 : 1.01 Derived type pointer + assumed shape 1 : 1.01 Regular array + assumed shape 2 : 1.00 Derived type pointer + assumed shape 2 : 1.01 Derived type pointer + Derived type : 1.01 Using array notation Regular array + assumed size : 1.00 Derived type pointer + assumed size : 1.00 Regular array + assumed shape 1 : 1.00 Derived type pointer + assumed shape 1 : 1.01 Regular array + assumed shape 2 : 1.00 Derived type pointer + assumed shape 2 : 1.00 Derived type pointer + Derived type : 1.01 testa Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.01 Derived type allocatable + assumed shape 1 : 1.01 Regular array + assumed shape 2 : 1.01 Derived type allocatable + assumed shape 2 : 1.01 Derived type allocatable + Derived type : 1.01 Using array notation Regular array + assumed size : 1.00 Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.01 Derived type allocatable + assumed shape 1 : 1.01 Regular array + assumed shape 2 : 1.01 Derived type allocatable + assumed shape 2 : 1.01 Derived type allocatable + Derived type : 1.00 ------------------------------------------------------------------------------- PathScale compiler Version 3.0, Linux AMD 64-bit. Build options (testp) pathf90 -O3 -c tlib.f90; pathf90 -O3 -c tdefp.f90; pathf90 -O3 -c tlibp.f90 ar cr tlib.a tlib.o tdefp.o tlibp.o; pathf90 -O3 -c ttestp.f90; pathf90 -O3 ttestp.o tlib.a; (testa) pathf90 -O3 -c tlib.f90; pathf90 -O3 -c tdefa.f90; pathf90 -O3 -c tliba.f90 ar cr tlib.a tlib.o tdefa.o tliba.o; pathf90 -O3 -c ttesta.f90; pathf90 -O3 ttesta.o tlib.a; testp Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type pointer + assumed size : 1.00 Regular array + assumed shape 1 : 1.03 Derived type pointer + assumed shape 1 : 1.02 Regular array + assumed shape 2 : 1.03 Derived type pointer + assumed shape 2 : 1.02 Derived type pointer + Derived type : 0.93 Using array notation Regular array + assumed size : 1.01 Derived type pointer + assumed size : 1.01 Regular array + assumed shape 1 : 1.03 Derived type pointer + assumed shape 1 : 1.02 Regular array + assumed shape 2 : 1.02 Derived type pointer + assumed shape 2 : 1.02 Derived type pointer + Derived type : 0.93 testa Abstraction penalty versus regular array + assumed size dummy argument + do loop (1 means no penalty) Using Do loop Derived type allocatable + assumed size : 1.00 Regular array + assumed shape 1 : 1.03 Derived type allocatable + assumed shape 1 : 1.03 Regular array + assumed shape 2 : 1.02 Derived type allocatable + assumed shape 2 : 1.03 Derived type allocatable + Derived type : 1.00 Using array notation Regular array + assumed size : 0.93 Derived type allocatable + assumed size : 0.96 Regular array + assumed shape 1 : 1.04 Derived type allocatable + assumed shape 1 : 1.03 Regular array + assumed shape 2 : 1.03 Derived type allocatable + assumed shape 2 : 1.02 Derived type allocatable + Derived type : 0.99 -------------------------------------------------------------------------------