Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29389 Discussions

Multimensional Arrays vs. Arrays of arrays (Performance)

rafadix08
Beginner
652 Views
Hello everyone,

I was trying to optimize my code and tried to transform a multidimensional array into an array of arrays, since many of the cells of the original multidimensional array are never used.

The way I constructed an array of arrays was by first defining a drived data type, containing a single pointer, and then constructing an array of this new type.

Here is what I did:

type :: ptr_to_array_real
real(KIND=DOUBLE), dimension(:), pointer :: arr
end type ptr_to_array_real

type(ptr_to_array_real) eps_global(N1,N2,N3)

Instead of having a bigger array eps_global(N1,N2,N3,N4) where, conditional on N1, N2 and N3, many cells of eps_global(N1,N2,N3,:) would never be used. Actually, the number of cells of eps_global(N1,N2,N3,:) that are used depend on N1, N2 and N3.

I noticed that instead of becoming faster, my program became slower, doubling the running time.

Is accessing cells of an array of arrays really slower?

Or is it the way I am allocating memory not efficient?

Here is what I do in order to allocate this array of arrays:

allocate(eps_global(N1,N2,N3))

do coh = FIRST_COH, LAST_COH
do n = 1, NPOP
do s = 0, NSECTORS
allocate(eps_global(n,coh,s)%arr(f(coh)))
end do
end do
end do

Is there a better way to the above block?

Many thanks,
Rafael
0 Kudos
5 Replies
Steven_L_Intel1
Employee
652 Views

Any time you add indirect references (through additional layers of pointers), you will slow down the code.
0 Kudos
rafadix08
Beginner
652 Views

Any time you add indirect references (through additional layers of pointers), you will slow down the code.

So in this case there is a tradeoff between efficient memory allocation and performance (in terms of speed)?

Is there another way to have an array of arrays in Fortran that does not depend on pointers?

Last question, can I have a loop over variables in Fortran?

For example, what would be the syntax (if any) for:

do i = 1, N
x"i" = 0
end do

That is, I am trying to access x1, x2, ..., XN with a loop. Can that be done in Fortran? If yes, how?

Many thanks,
Rafael
0 Kudos
jimdempseyatthecove
Honored Contributor III
652 Views

For your last question you can have a union of X(N) with X1, X2, ... XN

union
map
real :: X(N) ! INTEGER, PARAMETER :: N=3
end map
map
real :: X1, X2, X3
end map
end union
...
do i = 1, N
x"i" = 0
end do

...
foo = X1

I would suggest you modify the code to use X(1)

Jim
0 Kudos
rafadix08
Beginner
652 Views

For your last question you can have a union of X(N) with X1, X2, ... XN

union
map
real :: X(N) ! INTEGER, PARAMETER :: N=3
end map
map
real :: X1, X2, X3
end map
end union
...
do i = 1, N
x"i" = 0
end do

...
foo = X1

I would suggest you modify the code to use X(1)

Jim

What if X1, .., XN are arrays of different sizes?
0 Kudos
IanH
Honored Contributor III
652 Views
Quoting - rafadix08
Is there another way to have an array of arrays in Fortran that does not depend on pointers?


As a trivial, direct answer to your question (but not necessarily a useful recommendation) - yes:

type :: ptr_to_array_real
real(KIND=DOUBLE), dimension(:), ALLOCATABLE :: arr
end type ptr_to_array_real

Performance wise, this doesn't avoid the extra indirection but I guess could help eliminate some potential aliasing issues for the compiler (?). However, the issue discussed here and here suggest (if I understand the issue correctly) that you'd get exactly the same performance result as using POINTER anyway. I've not checked but it is a pity if that is the case - a lot of my allocatable arrays sit as components of derived types.

As an alternative to your original problem, you could chop a big 1-D array up into variable length bits, that is say indexed by a companion integer array of dimension (N1,N2,N3). The integer array points to the first ("zeroth" might be better) element in the big array that contains what now sits in your derived type. You then roll-your-own indexing into the big array based off that. Could get a bit complicated though - better you than me.

0 Kudos
Reply