5

I'm working with Fortran90, but I don't have a lot of familiarity with it.

In some point of the code, I would like to create an array of n linearly equally spaced points between t0 and tf, so I tried this:

t = t0+(/(i,i=0,n-1)/)*(tf-t0)/(n-1)

Which is the same thing as:

do while(i<=n)
    t(i) = i-1
    i=i+1
end do

t = t*(tf-t0)/(n-1)+t0

However, if n is too large (n=2000001 or bigger), the first option doesn't work. I get the error:

forrtl: severe (170): Program Exception - stack overflow

Why is that? What can I do to make the implied do loops work for n large?

1
  • Which compiler are you using?
    – casey
    Commented Mar 13, 2015 at 0:48

3 Answers 3

5

Some Fortran processors use a hardware stack for storage of temporaries created during evaluation of an expression. When the expression involves large objects - such as large arrays - the storage required for the temporaries may exceed the total storage available for the hardware stack, and the stack overflows.

In the first case it is likely that your Fortran processor is creating a large temporary to hold the result of the array constructor.

Different processors have differing capabilities in their ability to evaluate expressions without requiring temporaries - for example you may find that some processors also have stack overflow problems with your second example - the variable t that is assigned to is also referenced in the right hand side expression which may be enough for some Fortran processors to require evaluation of the entire right hand side to a temporary.

Your options are (perhaps in combination):

  • Use operating system or compiler switches to set aside more storage for the hardware stacks.

  • Use a compiler switch or similar that directs the processor to create temporaries on the heap instead of the stack.

  • Restate the overall operation in a different manner such that the compiler no longer creates temporaries (as you have already explored). This may include recasting the operation as an element by element operation in a do loop, rather than using operations directly on the arrays.

These approaches are platform specific. Based on the error message I guess you are using Intel Fortran (or an ancestor) on Windows - if so see the /heap-arrays compiler option and the Windows linker option /stack. If you are on linux see the ulimit command.

4

With the implied loop, a temporary array is created in the stack, while with the explicit loop, each element is processed separately and no temporary array is created. Stack size is by default limited and hence the error with a sufficiently large array.

I'll add to the third point made by IanH that in order to help decide whether to restructure the code in order to avoid temporary arrays, it is worth considering using -Warray-temporaries with gfortran and -check arg_temp_created or, better, -check all, with ifort.

2
  • 1
    The -check all is insane. Warns at every call, even inside a loop and warns even when passing a small array literal as an argument, which is completely harmless, the temporary just avoids creating an unnecessary variable cluttering the code.. Commented Mar 13, 2015 at 23:20
  • Well, maybe it's better for beginners then. A good programmer probably instinctively writes code that avoids large temporary arrays. For me it has been quite useful in the past. Commented Mar 14, 2015 at 11:28
2

There is nothing wrong with a simple loop like :

do i=1,n
   t(i)=t0+(i-1)*(tf-t0)/(n-1)
enddo

I am always surprised when people try absolutely to use array expressions which have often hidden drawbacks.

Not the answer you're looking for? Browse other questions tagged or ask your own question.