Question

I have done a lot of work with array-based interpreted languages, but I'm having a look at Fortran. What has just occurred to me after writing my first bit of code is the question of whether or not gfortran will optimise an expression using array syntax by placing the expression in a single loop. In most array-based interpreters an expression such as A=B/n*2*pi (where B is an array) would require 5 loops and multiple array temporaries to evaluate. Is gfortran clever enough to optimise this out, and will my code below (the line that calculates the array from 0 to 2pi) be as efficient as an explicit do loop around the expression? Is there anything I should look out for when using array syntax if I'm worried about performance?

PROGRAM  Sine
   IMPLICIT  NONE

   REAL, PARAMETER :: PI = 3.415926535
   INTEGER, PARAMETER :: z = 500
   INTEGER :: ier
   INTEGER, EXTERNAL :: PGBEG
   REAL, DIMENSION(z) :: x,y

   x=(indgen(z)-1.0)/z*(2*pi) ! This line...``
   y=sin(x)
   CALL plot(y,x)

   CONTAINS

     FUNCTION indgen(n) result(i)
       INTEGER :: n
       INTEGER, DIMENSION(n) :: i
       INTEGER :: l
       DO l=1,n
          i(l)=l
       END DO
     END FUNCTION indgen

    SUBROUTINE plot(y,x)
       REAL, DIMENSION(:) :: x,y
       ier=PGBEG(0,'/XWINDOW',1,1)
       CALL PGENV(0.0,7.0,-1.0,1.0,0,1)
       CALL PGLINE(SIZE(x),x,y)
       CALL PGEND()
     END SUBROUTINE plot

END PROGRAM Sine
Was it helpful?

Solution

In gfortran you can use the -Warray-temporaries flag to see all array temporaries generated. When I try your example no extra array temporary is generated (other than the one necessary to store the results of indgen(z)), so I guess gfortran is clever enough.

OTHER TIPS

The expression z*(2*pi) is a compile-time constant, which the compiler can easily verify, so that should not be evaluated at run time regardless. Additionally, virtually all modern compilers should perform one-line "elemental" array operations within a single loop, and in many cases SIMD instructions will be generated (auto-vectorization).

Whether a temporary is generated usually depends on whether or not each element can be handled independently, and whether or not the compiler can prove this. Xiaolei Zhu's suggestion of using -Warray-temporaries is a good one. Don't mix this up wih -fcheck=array-temps, which I think only applies to temporaries generated for function calls.

Here's an example of such a message from gfortran:

foo.F90:4.12:

foo(1:20) = 2*foo(20:1:-1)
            1
Warning: Creating array temporary at (1)

Your function call will be done in a separate loop, unless the compiler can inline it. Whether or not the compiler inlines a short function can be pretty unpredictable; it potentially depends on where that other function is defined, whether or not the function has the pure attribute (although in practice this rarely seems to matter), the vendor and version of the compiler itself, and the options you pass. Some compilers can generate a report for this; as I recall, the Intel compiler has a decent one.

Edit: It's also possible to inline the expression in this line pretty easily by hand, using an "implied do loop":

x = [ ( real(i)/z*(2*pi), i = 0, z-1) ]

Yes. Fortran is compiled rather than interpreted. It handles loops very well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top