C++Guns – RoboBlog

26.01.2015

Fortran save, data, static, global, parameter WTF?

Filed under: Allgemein — Tags: — Thomas @ 23:01

Whats the difference between between save, static, global, local and parameter variables?

Save and static are two words for the same thing.
I found a nice definition of what save do in the Fortran 77 Standard [1]

Within a function or subroutine subprogram, an entity specified by a SAVE statement does not become undefined as a result of the execution of a RETURN or END statement in the subprogram


subroutine func()
  implicit none
  real, save :: time
  time = time + 1
  write(*,*) time
end subroutine

program test
  implicit none
  integer :: i
  do i = 1, 10
    call func()
  end do
end

1.00000000
2.00000000
3.00000000
4.00000000
5.00000000
6.00000000
7.00000000
8.00000000
9.00000000
10.0000000

You can count how often a subroutine is called. If you ever want to do this... I can not recommend to do it in this way.
As you may have noticed, I have not initialized the time variable with an start value.
You can do this with the data instruction.


subroutine func()
  implicit none
  real :: time
  data time/100/  
  time = time + 1
  write(*,*) time
end subroutine

101.000000
102.000000
103.000000
104.000000
105.000000
106.000000
107.000000
108.000000
109.000000
110.000000

The save specifier is not needed by using the data keyword.
This may result in confusion, because not everybody knows exactly what the data specifier does.
Again: do not use it.

The greatest pitfall with static variables is this:


real :: time = 0

If you initialize a variable by the declaration, it become a static variable! That really really hurts. You want be a good programer and always zero your variables and then you crash the hole program :D

Lets talk about parameters. Many programmers declare they constans with the save attribute.
I can not recommend this.
First: Constants does not change. Variables with save attribute can change.


real, save :: PI = 3.14...
PI = 4

All fine ;)

If you use parameter instead of save the compiler can detect this issue.


real, parameter :: PI = 3.14...
PI = 4

PI = 4
1
Error: Named constant 'pi' in variable definition context (assignment) at (1)

Second: Fortran is a high performance language. You can easily vectorize assigments using the forall constrcut.
All functions called from the forall constrcut must be declared as pure. to ensure that they have no side effects.


  function func() result(val)
    implicit none
    real, save :: PI = 3.14
    real :: val
    val = PI
  end function

forall( i = 1:100 ) A(i) = func()

forall( i = 1:100 ) A(i) = func()
1
Error: Reference to non-PURE function 'func' at (1) inside a FORALL block

And a pure function can not have static variables


  pure function func() result(val)
    implicit none
    real, save :: PI = 3.14
    real :: val
    val = PI
  end function

real, save :: PI = 3.14
1
Error: SAVE attribute at (1) cannot be specified in a PURE procedure

Using parameter solves the issue


  pure function func() result(val)
    implicit none
    real, parameter :: PI = 3.14
    real :: val
    val = PI
  end function

forall( i = 1:100 ) A(i) = func()

$ ifort -O2 -c save.f90 -vec-report3
save.f90(19): (col. 25) remark: LOOP WAS VECTORIZED

The last thing I talk about are global variables.
They can be accessed and overwritten from everywhere by everyone anytime. Happy bug chasing...
One way to create global variables in Fortran is using the COMMON keyword. I allready wrote about that..

[1] http://www.fortran.com/fortran/F77_std/rjcnf-8.html#sh-8.9

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress