Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Initializing a subroutine

Don_O
Beginner
1,505 Views

I've justmovedfrom an older compiler/F77to 11.1.035/F90/IDE and am trying to time several algorithms. The following illustrates what Ithought wasthe way to initialize a subroutine:

subroutine abc (x,y)

real*8 x,y,a1

real*8 b1,b2

logical, save :: first

data /.first./

if (first) then

first = .false.

a1 = user defined parameter

b1= needed constant

b2 = needed constant

endif

y = f(x,b1,b2)

end

ButI'm gettingerratic results.One programrunsin half the timeif Iremove theIF statement, meaning the compiler knows toONLY compute the constants once. Theapproach above indicates whatI want to do, but the compilerdoesn't seem to like it.Would prefertoprogram the algorithm the same way I'dwriteitin a report.

Anythoughtsonthe best way to initialize subroutineswould be appreciated.

Don

0 Kudos
6 Replies
Steven_L_Intel1
Employee
1,505 Views

You need SAVE on all the variables you're initializing, such as a1, b1, b2. You may have used a compiler that gave you implied SAVE semantics, but without SAVE your code is not legal Fortran and Intel Fortran does not imply SAVE.

See Better SAVE Than Sorry

I assume that there's a .true, on that DATA statement.

Of course, another way to handle this is to DATA initialize the variables - it will accomplish the same thing without the need for the IF test.

0 Kudos
Don_O
Beginner
1,505 Views

Steve, sorry for the typos. I'll paste the actual code of thebeginning of the subroutine.The main programcalled ita billion times andthe total cpu time was75 seconds:

subroutine methodA (w,z,L,H)

implicit none

real*8 w,z,L,H,f,e2,e4,e8,d,s,k,t,g,n,c,u,v,q,m,p

real*8, save :: a,a1,a2,a3,b1,b2,b3,b4,b5

logical, save :: first

data first /.true./

if (first) then

first = .false.

a = 6378137.d0

f = 1.d0/298.257222101d0

e2 = (2.d0-f)*f

a1 = a*e2

a2 = 0.5d0*e2

a3 = 1.d0-e2

e4 = e2*e2

e8 = e4*e4

b1 = .50000000000013d0*e2

b2 = .374999999778d0*e4

b3 = .3125001354d0*e4*e2

b4 = .27340019d0*e8

b5 = .250831d0*e8*e2

endif

d = 1.d0/dsqrt(w*w+z*z)

s = z*d

k = a1*d

With the changes below, the program ran in 40 seconds and got the right answer:

subroutine methodA (w,z,L,H)

implicit none

real*8 w,z,L,H,f,e2,e4,e8,d,s,k,t,g,n,c,u,v,q,m,p

real*8, save :: a,a1,a2,a3,b1,b2,b3,b4,b5

! logical, save :: first

! data first /.true./

! if (first) then

! first = .false.

a = 6378137.d0

f = 1.d0/298.257222101d0

e2 = (2.d0-f)*f

a1 = a*e2

a2 = 0.5d0*e2

a3 = 1.d0-e2

e4 = e2*e2

e8 = e4*e4

b1 = .50000000000013d0*e2

b2 = .374999999778d0*e4

b3 = .3125001354d0*e4*e2

b4 = .27340019d0*e8

b5 = .250831d0*e8*e2

! endif

d = 1.d0/dsqrt(w*w+z*z)

s = z*d

k = a1*d

Don

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,505 Views

When you comment out the initialization code the aggressive optimization capability of the compiler can observe the literal initialization expressions (including variables used in an expression and which were immediately re-initialized). For these variables, subsequent use in your code can result in the code can be generated to use the immediate values (andliteral expression results)that were used to load the variables in substitution for the values just written into those variables. Also, for less aggressive optimization, the registers used to produce the results of the initialization of those variables can be used in place of re-fetching the contents of memory held by the variable.

While the re-initialization method will incur more writes (which need not stall the processor) it will also endure fewer reads (which generally stall the processor).

>> But I'm getting erratic results.

Look for bug in program that alters the SAVE'd variables.

>>One program runs in half the time if I remove the IF statement, meaning the compiler knows to ONLY compute the constants once.

Not necessarily true (see first paragraph). The compiler knows not to re-read something it already knows is laying around in a register or is a literal that can be loaded using an immediate value.

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
1,505 Views

You are still missing SAVE for e2, e4 and e8.

But why are you doing this at all? None of these are modified in the routine, and many are not even referenced (at least in what you have shown us.) If these values get set once and never modified, please change them to PARAMETERs. You'll find the code gets much faster.

0 Kudos
Don_O
Beginner
1,505 Views

The e2, e4, e8 were just intermediate variables, and all the saved constants were referenced and unmodified(I just didn'tlist the entire subroutine).

I'm now using the PARAMETER statement as you suggested,and itseems MUCH better/cleaner. Out of laziness, I had beenkeeping the initialization equations in the subroutine, but the reality is that once an Earth model (a,f) is chosen, it's not changed. Two accurateEarth models exist, but only one (WGS-84)is used in the U.S.

BTW, where can I learn about compiling and executing at the command-line? I've searched the online reference and I'm still a bit unclear. ICAN copy a source file to c:\windows\system32 andI DO know DOS. Since I'm only compilingsimple programs, maybe I don't need a makefile.

Thanks,

Don

0 Kudos
Steven_L_Intel1
Employee
1,505 Views

The on-disk documentation, under Building Applications > Building Applications from the Command Line, describes use of the command line. You will want to start your command line session by invoking Start > All Programs > Intel Software Development Tools > Intel Fortran Compiler 11.1.xxx > Build Environment for Applications running on [IA-32 or Intel 64].

Do not copy source files to windows\system32! Use a folder not under Windows. I use C:\Projects but it's up to you.

0 Kudos
Reply