- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Any time you add indirect references (through additional layers of pointers), you will slow down the code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - Steve Lionel (Intel)
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - jimdempseyatthecove
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page