1

I can reallocate an allocatable variable or array without the explicit deallocate/allocate procedure as explained in Automatic array allocation upon assignment in Fortran if my compiler is Fortran 2003 compliant. E.g.

integer, allocatable :: i(:)

i = [1,2,3]
i = [1,2,3,4,5]

versus the old (Fortran 90) way:

if( allocated(i) ) deallocate(i)
allocate(i(3))
i = [1,2,3]
if( allocated(i) ) deallocate(i)
allocate(i(5))
i = [1,2,3,4,5]

What or the adventages and disadvantages of this newer technique? It's certainly much more concise code than the old way. But are there reasons to prefer the old way? I still see the old way in code examples much moreso than the new way, but maybe it's just because Fortran 90 is still used more than Fortran 2003.

As a quick timing check, I looped the above code 100,000,000 times under gfortran 4.8.5 and found that the newer way also seems to be faster, running in about 4 seconds (new way) vs 6 seconds (old way). Conversely, in the comments below @roygvib gets essentially the opposite result with gfortran 8.2.

Also, note this recent discussion of the issue here: Fortran Discussion Group

JohnE
  • 29,156
  • 8
  • 79
  • 109
  • In the dupe question see **Linked** on the right for many more similar questions. – Vladimir F Героям слава Feb 04 '19 at 22:25
  • In that case you should write your question in such a way that it is clearly about the non-dupe aspects, not add an edit that still leaves those points that are explained elsewhere, re-write the question! OK, I did it for you... – Vladimir F Героям слава Feb 05 '19 at 09:23
  • 1
    The other questions seem to revolve around the theme of "I have a bug" whereas this question concerns the comparison between two programming styles. – Pierre de Buyl Feb 05 '19 at 14:31
  • @JohnE There is nothing nothing stopping you to refine the question stopping you from refining the question while it is closed or "on hold". Quite the opposite, the closure message usually explicitly contains instructions what could be done to have it reopen. Alas, I did such an edit myself and re-opened your question afterwards. – Vladimir F Героям слава Feb 05 '19 at 15:39
  • @VladimirF Right, and I appreciate that but most people aren't even going to glance at a question after it's closed. Simply leaving it open for a few hours before closing will give it a chance to get some views first. – JohnE Feb 05 '19 at 15:44
  • The point is to make you change the question to be on-topic, not to let people answer an off-topic question. But this should be discussed elsewhere, preferably on the meta. – Vladimir F Героям слава Feb 05 '19 at 15:49
  • @VladimirF In the original question, I asked: **"Is this a bad idea or is it OK? It's certainly much more concise code"**. I agree your edit made things more clear and also appreciate the link to the semi-dupe question but all of that can be done without insta-closing the question. All I'm asking is to let a question sit for a short amount of time before closing based on one person's opinion which is often, but not always, correct. – JohnE Feb 05 '19 at 16:13
  • 1
    I've just tried comparing the above two patterns for 10^8 loops, but the second version was faster (by ~40%) with gfortran-8.2 -O3. On the other hand, a bit old PGI fortran gives essentially the same timing. So the results may vary depending on compilers? – roygvib Feb 06 '19 at 02:48
  • @roygvib Thanks for comparison timings. I used defaults for gfortran 4.8.5. Not surprising there are differences although I would have expected them to be smaller and perhaps more consistent but perhaps not. Still interesting in that it suggests compilers do not implement the two code variants identically altho they would seem to be doing almost the same thing. – JohnE Feb 06 '19 at 03:57
  • With gfortran-8 on [TIO](https://tio.run/#) (which runs on Ubuntu), the first version was faster by 10%, so it may also depend on OS/memory allocation methods etc etc. For lower-level codes, -fdump-tree-original (or even -S) may give more hints (but I give up at this point XD – roygvib Feb 06 '19 at 04:17
  • There is no reason the code should be identical. One can be done by the runtime library in a single step, the other are to calls to Fortran statements which are very likely to be done by two calls to runtime library routines. There is a place for optimizations when everything is done in a single step. That's why I mentioned realloc in my answer. – Vladimir F Героям слава Feb 06 '19 at 07:32

2 Answers2

5

I will list the differences, what is an advantage or disadvantage is subjective.

The compiler has to check the correct bounds on each whole-array assignments - but that has to happen anyway, even if you do not use the reallocation. Unless you completely disable this standard feature in some compilers.

For those that are not used to dynamic languages where most assignments do some allocation it may be a substantial fact that in deallocate and reallocate statements it is explicitly visible that reallocation is in fact happening.

With automatic reallocation the compiler could potentially use realloc, especially in cases like a = [a, 1]. But as far as I know compilers do not currently do that. Nevertheless, the usual malloc will often re-use the memory where the old array was if it fits there.

3

The advantage is the conciseness of the code.

integer, allocatable :: i(:)

i = [1, 2, 3]

has one less line than

integer, allocatable :: i(:)

allocate(i(3))
i = [1, 2, 3]

Also, you do not need to write explicitly the size of the allocation, so there is a little less redundant information.

The incovenient is that it is an automatic feature.

I can think readily of two scenarios where the feature is a disadvantage.

  1. The array i is reallocated on assignment for good reasons (i.e. not a bug in the code) and introduces a performances penalty that may be harder to find.
  2. The array i is reallocated because of a logic error in the code. This bug would be easier to detect is the consequent out-of-bound memory access threw a segfault :-)

You might detect "2" with compiler checks and solve "1" with a profiler, though. So, unless you have a good reason not to use the feature, I'd say "use it". For existing code bases, however, there is no specific motivation to remove the allocate statements "just because".

Pierre de Buyl
  • 7,074
  • 2
  • 16
  • 22
  • 1
    You almost always need a line for `if(allocated(foo)) deallocate(foo)` unless you know you will allocate exactly one time and even then it's safer to include that. So generally it's 2 extra lines not 1. – JohnE Feb 05 '19 at 21:23
  • I considered a single allocation but of course for reallocation of a variable you need more logic. – Pierre de Buyl Feb 06 '19 at 08:41