experchange > fortran

gah4 (02-04-19, 11:18 PM)
Recent thread on ALLOCATE reminds me, and in a few places
mentions, the problem of changing the size of an array
while keeping existing data.

C has the realloc() function to do this, which might require
copying data, but with appropriate library and OS support,
can sometimes do it in place.

For Fortran 90 and 95, one could:

Allocate a temporary array.
Copy data from old to new array.
Deallocate original array.
Allocate original array to new size.
Copy data back.
Deallocate temporary array.

More recently, the MOVE_ALLOC feature allows:

MOVE_ALLOC original array somewhere else.
Allocate new array to new size.
Copy data over.
Deallocate moved original array.

So now one copy instead of two.

The C realloc() function has the ability, with no guarantee,
of increasing the size in place. Some systems do this if it
is at the end of allocated memory, or otherwise there is
enough unallocated space after it. Otherwise, it nicely copies
the data for you, maybe more efficiently than otherwise.
robin.vowels (02-10-19, 03:05 AM)
On Tuesday, February 5, 2019 at 8:18:27 AM UTC+11, ga...@u.washington.edu wrote:
[..]
> Deallocate temporary array.
> More recently, the MOVE_ALLOC feature allows:
> MOVE_ALLOC original array somewhere else.


Requires a move.

> Allocate new array to new size.
> Copy data over.


Requires a move.

> Deallocate moved original array.
> So now one copy instead of two.


Surely still two?
Ron Shepard (02-10-19, 10:51 AM)
On 2/9/19 7:05 PM, robin.vowels wrote:
>> More recently, the MOVE_ALLOC feature allows:
>> MOVE_ALLOC original array somewhere else.

> Requires a move.


The MOVE_ALLOC step is a shallow copy. No data is actually moved.

>> Allocate new array to new size.
>> Copy data over.

> Requires a move.
>> Deallocate moved original array.
>> So now one copy instead of two.

> Surely still two?


One shallow copy and one actual data move. And you can do those two
steps in either order. It is sometimes better to ALLOCATE first and then
MOVE_ALLOC last.

There are some situations where the programmer can control the
reallocation in place. For example, if you know the maximum size of the
arrays ahead of time, you can do a single allocation of the maximum
workspace, and then do pointer assignments into that workspace with the
actual correct array bounds. Now that pointer assignment of higher rank
arrays to rank-1 target arrays is allowed, you can do this for arbitrary
arrays. Another possibility might be the ASSOCIATE construct, but I have
not yet tried that in this kind of situation. And another way is to use
storage sequence association in the f77 way to associate a correctly
dimensioned dummy argument with the workspace array.

In these cases you aren't really doing memory reallocation, you are
reusing the same memory and instead manipulating the meta data to get
arrays with the right ranks and bounds.

$.02 -Ron Shepard
FortranFan (02-11-19, 05:54 AM)
On Monday, February 4, 2019 at 4:18:27 PM UTC-5, ga...@u.washington.edu wrote:

[..]
> Deallocate moved original array.
> So now one copy instead of two.
> ..


Yes, but the "canonical" steps per "modern Fortran to resize an array can be the following:

1) Allocate a temporary new array to desired new size.
2) Copy data from original array to desired location in the new temporary array.
3) Use MOVE_ALLOC intrinsic to move the allocation FROM the new temporary array TO the original array.

In code, it may be as follows:

<type>, .. , ALLOCATABLE :: foo(:,..)
..
allocate( foo(..) )
..
block_resize: block
<type>, .. , ALLOCATABLE :: tmp(:,..)
tmp(1:size(foo,dim=..) = foo !<-- assignment copy
call move_alloc( FROM=tmp, TO=foo ) !<-- move
end block block_resize

Fortran standard can potentially introduce an intrinsic to achieve this, especially to make matters easier for coders while extending further flexibility to compilers to bring in whatever elements of efficiency they can employ within their implementations with these copy-move steps.
Similar Threads