Variable size arrays in Fortran without Allocate()
Asked Answered
A

2

15

Is there a way to create variable size arrays in Fortran on the stack? Allocate() does not work for me, because it places the array on the heap. This may lead to problems with parallelization (see my other question: OpenMP: poor performance of heap arrays (stack arrays work fine) ). Of course, some smart memory management would give a way around that problem, but memory management in Fortran sounds silly.

Essentially, I am looking for a Fortran equivalent of the following in C:

scanf("%d", N);
int myarray[N];

To re-iterate: I do NOT want

Integer, PARAMETER :: N=100
Integer, Dimension(N) :: myarray

because this determines the array size at compile time. Neither do I want

Integer, Dimension(:), Allocatable :: myarray
read(*,*) N
Allocate(myarray(1:N))

because it places the array on the heap.

Help very much appreciated. I was very happy with Allocatable arrays until my recent encounter with the problem in the question cited above. If there is a negative answer to this question, I would very much appreciate a link to the source.

Edit: see comments to M.S.B.'s answer. An elegant way of doing this only became possible in Fortran 2008, and it is done in a block construct.

Ammonium answered 7/7, 2011 at 20:51 Comment(2)
Last time I checked this way of allocating arrays in C was non-standard but supported by some compilers. AFAIK, though, they're not much more than "syntactic sugar" and basically do the same thing ans an alloc so, I'd say, still allocate on the heap.Repulsion
Variable size arrays on the stack don't work (in C) I believe, because the compiler needs to know where to access stack variables at compile time.Repulsion
R
17

Fortran can automatically create arrays just with declarations on entry to subroutines, as long as the the dimensions are known at run time ... this doesn't require the dimensions to be declared parameter attribute, they can be arguments, e.g.,

subroutine MySub ( N )

integer, intent (in) :: N
real, dimension (N) :: array

is valid. So why not decide your size "N" in the main program, or some subroutine, then call another subroutine to continue. Likely with this approach the array will be on the stack. As @eriktous wrote, the Fortran language standard doesn't specify this behavior. Some compilers switch local arrays to the heap past a certain size. Some compilers provide options to control this behavior. Placing large arrays on the heap would probably be overridden with recursive or OpenMP.

You can also pass an allocatable array as an actual argument to a subroutine without the dummy argument of the subroutine being declared as allocatable. Which may not help with your concern because the original array will still likely be on the heap.

Re answered 8/7, 2011 at 1:33 Comment(5)
Thanks, M.S.B.! As heavy as it is compared to C's int array[N], it does the trick.Ammonium
You can do something closer to C, i.e., a declaration in the middle of the code, using Fortran 2008's block construct. See, for example, p. 12 of ftp.nag.co.uk/sc22wg5/N1701-N1750/N1729.pdf. I don't know which compilers support this, or whether they support it with OpenMP.Re
I have this construct in my code, however I notice that by default gfortran still puts the arrays on the heap, and now I have malloc in the middle of my tight loops. It seems that the option "-fstack-arrays" is needed.Charlottcharlotta
Just giving some history I know. Variable size arrays (automatic arrays) in subroutines, as a useful feature for numerical computation, is supported since (or before) Fortran77 whereas C began to support this only since C99. Linus Torvalds has expressed his displeasure in the past over variable length array usage with comments like ‘‘USING VLA'S IS ACTIVELY STUPID! It generates much more code, and much slower code (and more fragile code), than just using a fixed key size would have done.''Ventail
What exactly do you mean by as long as the dimensions are known at run time? If they're not known at run time, when will they ever be known? :)Repulsion
I
9

The Fortran standard has no concept of stack and heap, so this will be implementation (i.e. compiler) dependent. Looking at the docs for e.g. gfortran, it has an option

-frecursive
    Allow indirect recursion by forcing all local arrays to be allocated on the stack.

Other compilers may have similar options. Perhaps this does what you want.

Intrepid answered 7/7, 2011 at 21:56 Comment(2)
Thanks, that is an interesting idea! However, 'Local' arrays, to which this applies, are arrays created in functions, to which array size is passed as an intent(in) argument. In my tests, -frecursive had no effect on the results of Allocate(), but did have an effect on this interesting workaround: subroutine doit(n); integer, intent(in) :: n; integer, dimension(1:n) :: myarray; ! blah ; end subroutine ... read(*,*) n; call doit(n) In this case, myarray seems to get on the stack with and without -frecursive. A little perverted, but does the trick. I am using gcc 4.4.3 on x86_64.Ammonium
@drlemon: Right, I was afraid this particular option wouldn't exactly do what you needed. Gcc 4.4.3 is kind of old, especially from a Fortran point of view; gfortran development has been (and still is) pretty active. If possible, you could try if a newer version still exhibits the same problem. Also, if I were you, I would ask your question on the gfortran mailing list. Since this concerns specifics of implementation, the developers would know best what's possible and what's not.Intrepid

© 2022 - 2024 — McMap. All rights reserved.