Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A question on reallocation

179 views
Skip to first unread message

GianLuigi Piacentini

unread,
Nov 15, 2023, 1:40:07 PM11/15/23
to
Hi all,

I have a perhaps silly question, that puzzles me before committing to
write actual code.

Please consider a data structure which is basically an array of arrays
type element
integer, allocatable :: element_core(:)
end type
...
type(elements), allocatable :: array_of_elements(:)
...
allocate ( array_of_elements(some_size) )

(this is not a matrix, each element may significantly differ in size,
and someone may be long (and subjected to reallocation cycles, but his
is plain reallocation).

Now I have to increase size of previously allocated array_of_elements,
using the usual pattern (at least I think it's usual)

type(elements), allocatable :: tmp(:)

allocate ( tmp(new_size) )
tmp(1:some_size) = array_of_elements ! ***
call move_alloc(from = tmp, to = array_of_elements)

Seems to me that during the operation marked with the *** comment the
various elements are also copied, and this seems vasteful.
Is there a way to avoid such copying, if it really happens ?

Perhaps making array_of_elements an array of pointers to allocated
elements ?

Thanks in advance
Gigi Piacentini

gah4

unread,
Nov 15, 2023, 11:19:07 PM11/15/23
to
On 11/15/23 10:40 AM, GianLuigi Piacentini wrote:
> Hi all,
>
> I have a perhaps silly question, that puzzles me before committing to
> write actual code.
>
> Please consider a data structure which is basically an array of arrays
> type element
>   integer, allocatable :: element_core(:)
> end type
> ...
> type(elements), allocatable :: array_of_elements(:)
> ...
> allocate ( array_of_elements(some_size) )

(snip)

> type(elements), allocatable :: tmp(:)

> allocate ( tmp(new_size) )
> tmp(1:some_size) = array_of_elements                   ! ***
> call  move_alloc(from = tmp, to = array_of_elements)


I think you want something like:

allocate(tmp(new_size))

do i=1, old_size
call move_alloc(from=array_of_elements(i), to=tmp(i))
end do

call move_alloc(from = tmp, to = array_of_elements)

So, move all the subarrays over, then move the array of arrays.

Since only the, fairly small, array_of_elements is being reallocated,
it should be pretty fast.

Before move_alloc, you had to create a temporary, copy them over,
reallocate the original one, and copy them back. Lots of copying!

m_b_metcalf

unread,
Nov 18, 2023, 4:29:37 AM11/18/23
to
GianLuigi,

Does this do what you wanted?

Mike

P.S. This is also for me a trial posting using nemoweb.

type elements
integer, allocatable :: element_core(:)
end type

type(elements), allocatable :: array_of_elements(:)

type(elements), allocatable :: tmp(:)

allocate ( array_of_elements(3) )

allocate(array_of_elements(3)%element_core(3))

array_of_elements(3)%element_core(3) = 3


allocate ( tmp(4) )

call move_alloc(from=array_of_elements(1:3), to=tmp(1:3)) !<------

call move_alloc(from = tmp, to = array_of_elements)
print*, array_of_elements(3)%element_core(3)
end


GianLuigi Piacentini

unread,
Nov 19, 2023, 7:10:48 PM11/19/23
to
Thanks to all replier.

I ewconsidered the problem in light of the whole project, coming with 2
possible solutions:

1) since data come from analysis of several files, which do not change
during program execution, I can do a 1st pass counting dimensions, then
allocate, then do a 2nd pass reading data into the data structure.

2) as suggested, I could do
type element
integer, allocatable :: element_core(:) ! an array of integers
end type
type element_pointer
type(element), pointer :: e_p => null() ! pointer to the above
end type element_pointer

type(element_pointer), allocatable :: array_of_elements(:)

allocate( array_of_elements(3) ) ! an array of 3 pointers
do i = 1, size(array_of_elements)
allocate (array_of_elements(i)%e_p%element_core(n))
! where n is the size required for the ith array of integers
end do
... ! loading integers

Now when reallocating

type(element_pointer), allocatable :: tmp(:)

allocate( tmp(new size for array of array of integers) )

! copying pointers:
tmp(1:size(array_of_elements))%e_p => array_of_elements%e_p
! during this copy, in my intention, the underlying element_cores will
not be moved
call move_alloc (from = tmp, to = array_of_elements)

However, at the moment I cannot test the above machinery, I will do it
as soon as I can restart my hobby project, which will happen in some days.
But I am still interested in the subject, and in your comments, if any.

Thanks
Gigi


0 new messages