Fortran

From PHASTA Wiki
Revision as of 14:28, 18 October 2020 by Jrwrigh (talk | contribs) (Created page with "'''Fortran''' (short for '''For'''mula '''Tran'''slation) is a programming language geared towards numerical computation. == Miscelaneous Notes == === Equivalence Statemen...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Fortran (short for Formula Translation) is a programming language geared towards numerical computation.


Miscelaneous Notes

Equivalence Statement

The equivalence statement allows different variable names to reference the same "data" (read as memory allocation). A common paradigm in PHASTA is the use of temporary arrays to store the result of calculations that maybe reused multiple times. For example, the function fun_prod below calculates sum over i of [ 2* (a * b)_i + sqrt(a * b)_i ], where a and b are vectors:

real function fun_prod1(a, b)
    implicit none
    real, intent(in), dimension(4) :: a, b
    real, dimension(4) :: temp, sqrtab
    integer :: i

    temp = a*b
    sqrtab = sqrt(temp)
    temp = temp * 2.
    fun_prod1 = sum(temp + sqrtab)

    return
end function fun_prod1

While reusing the temp array for both a*b and 2*a*b is memory efficient (as we only need to have 2 1x4 arrays) and computationally efficient (as we calculate a*b only once), it's not very easy to read as the definition of temp changes throughout the code.

To improve the legibility, we could set a*b and 2*a*b to be different variables instead:

real function fun_prod2(a, b)
    implicit none
    real, intent(in), dimension(4) :: a, b
    real, dimension(4) :: ab, ab2, sqrtab
    integer :: i
    
    ab = a*b
    sqrtab = sqrt(ab)
    ab2 = ab * 2.
    fun_prod2 = sum(ab2 + sqrtab)

    return
end function fun_prod2

This is easier to read, as the contents of ab and ab2 are far less ambiguous. However, note that we are less memory efficient than before; we now require 3 1x4 arrays compared to the previous 2. This may not seem like much, but memory speed is often the bottle-neck when it comes to HPC performance, so a 50% increase in required memory is significant.

However, using the equivalence statement, we can get the best of both worlds:

real function fun_prod3(a, b)
    implicit none
    real, intent(in), dimension(4) :: a, b
    real, dimension(4) :: equiv__ab, equiv_2ab, sqrtab
    equivalence (equiv_ab, equiv_2ab)
    integer :: i
    
    equiv_ab = a*b
    sqrtab = sqrt(equiv_ab)
    equiv_2ab = equiv_ab * 2.
    fun_prod3 = sum(equiv_2ab + sqrtab)

    return
end function fun_prod3


Here, eqab</code and <code>eq2ab use the same memory, thus we only require 2 1x4 arrays. fun_prod3 is compiled as completely identical to fun_prod1, but it's more easily readable.

Note: equivalence can unexpected results if the programmer is not aware that two variables are made equivalent. That is why the variables ab and ab2 in fun2_prod were changed to equiv_ab</code and <code>equiv_2ab. This serves as a reminder that variables with the prefix equiv_ belong to the same memory space, and thus cannot be treated as different.