- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have something similar to the following:
do a=0,5
phi(0,a,x,y,z) = ...
do b=1,a
phi(b,a,x,y,z) = ...
enddo
enddo
This results in the phi array being about 2x larger than it needs to be. Phi can grow quite large sometimes, and there are some sizable performance and memory savings to be achieved by "flattening" the first two indices:
phi_idx=0
do a=0,5
phi(phi_idx,x,y,z) = ...
phi_idx=phi_idx+1
do b=1,a
phi(phi_idx,x,y,z) = ...
phi_idx=phi_idx+1
enddo
enddo
However, doing this makes the code significantly harder to follow, and makes the data more difficult to retrieve. Is there any way to store this data in a contiguous block of memory, but still leave it accessible by the "a" and "b" indices? There are also loops over "X", "Y", and "Z" (not included for the sake of clarity), so creating a whole bunch of pointers seems like it would take up a ton of space and negate the memory savings.
Thanks,
Greg
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There are several important points that remain obscure in what you wrote, so it is difficult to know if the following suggestion is off the point:
You can replace your flattened code by
I have not seen an effective Fortran implementation of triangular and trapezoidal arrays, such as those that can be implemented in C using the somewhat error-prone representation of a 2D array as an array of pointers to 1D arrays, with the pointers adjusted to point at illegal memory addresses to create the illusion of the same easy access to elements as in a rectangular 2D array.
You can replace your flattened code by
[fortran]ip=0provided that you know how the expression denoted by "..." depends on a and b .
do a=0,5
do b = 0,a
phi(ip,x,y,z) = ...
end do
ip=ip+a+1
end do
[/fortran]
I have not seen an effective Fortran implementation of triangular and trapezoidal arrays, such as those that can be implemented in C using the somewhat error-prone representation of a 2D array as an array of pointers to 1D arrays, with the pointers adjusted to point at illegal memory addresses to create the illusion of the same easy access to elements as in a rectangular 2D array.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Consider something along the line of:
type phi_t
real, allocatable :: xyz(:,:,:) ! x, y, z
end type phi_t
type(phi_t), allocatable :: phi(:,:) ! b, a
...
phi(b,a)%xyz(x,y,z)
Jim Dempsey
type phi_t
real, allocatable :: xyz(:,:,:) ! x, y, z
end type phi_t
type(phi_t), allocatable :: phi(:,:) ! b, a
...
phi(b,a)%xyz(x,y,z)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Doesn't that still create an array that is b x a? The issue is that I really only need roughly (bxa)/2 elements. Perhaps something like:
and then...
This would give me phi(x,y,z)%a(na)%b(nb), but I'm not sure about the ordering in memory. Would these be contiguous in memory, as implied in my original post, as would be the case with a standard array ordered as phi(b,a,x,y,z)?
type b_type
real,allocatable :: b(:)
end type
type a_type
type(b_type),allocatable :: a(:)
end type
type(a_type),dimension(:,:,:),allocatable :: phi
real,allocatable :: b(:)
end type
type a_type
type(b_type),allocatable :: a(:)
end type
type(a_type),dimension(:,:,:),allocatable :: phi
and then...
allocate(phi(X,Y,Z))
do iz=1,Z
do iy=1,Y
do ix=1,X
allocate(phi(ix,iy,iz)%a(0:ipn))
do na=0,ipn
allocate(phi(ix,iy,iz)%a(na)%b(-na:na)); phi(ii,ij,ik)%a(na)%b(:)=0.0
enddo
enddo
enddo
enddo
This would give me phi(x,y,z)%a(na)%b(nb), but I'm not sure about the ordering in memory. Would these be contiguous in memory, as implied in my original post, as would be the case with a standard array ordered as phi(b,a,x,y,z)?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[bash]In your original code you had phi(b,a,x,y,z)=... And used within do a=0,5 do b=1,a phi(b,a,x,y,z)=... enddo enddo My recommendation was to start with: type phi_t real, allocatable :: xyz(:,:,:) ! x, y, z end type phi_t type(phi_t), allocatable :: phi(:,:) ! b, a This would create a 2D array of array descriptors (allocatable arrays) However, you would only allocate those in the lower diagonal. Subsequent to this, you could eliminate the empty array descriptors by extending the sketch code to: type phi_t real, allocatable :: xyz(:,:,:) ! x, y, z end type phi_t type phi_b_t type(phi_t), allocatable :: b(:) ! a end type phi_b_t type(phi_b_t), allocatable :: phi(:) ... allocate(phi(0:5)) do a=1,5 ! *** allocate starting at 1 (0't is empty) allocate(phi(a)%b(a)) do b=1,a allocate(phi(a)%b(a)%xyz(nX,nY,nZ) enddo enddo ... do a=0,5 do b=1,a phi(b)%b(a)%xyz(x,y,z)=... enddo enddo Note, the xyz 3D array will be contiguous memory (with x index having adjacent cells) Jim Dempsey[/bash]

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