Hello,
This is not so much a question as observationa I made making some
experiments this weekend concerning aliasing and array components in
derived data types:
I have complained before about two major problems with array pointers in
F90:
1) possible non-contiguity--which can be a problem when passing arrays
as actuals for assumed-size arrays (granted, we agreed a run-time check
is good in this case)
2) possible aliasing--which causes temporary copies to be made by some
compilers in statements like a=b+c. I am not sure which if any compilers
do run-time checks here to determine if overlapping actually occurs?
By allowing allocatable components in derived types, F95+TR's definitely
solves problem 1. I had thought at first it would solve problem 2 as
well. However, in my codes I definitely need some kind of dynamic
character of the arrays, in the sense that one array needs to be
associated with several data-types (they need to share it), or I may
have two possible arrays that I want to associate with in turn.
So imagine a type like:
type allocatable_array
real, allocatable, dimension(:) :: array
end type allocatable_array
and then:
type main_type
type(allocatable_array), pointer :: A, B, C
end type main_type
The objects A, B and C are something in-between an array pointer and an
allocatable array, and as far as problem 1 is concerned, guaranteed to
be contiguous. But A can still be alliased with B or C, so one compiler
I use will make temporaries for things like A%array=B%array+C%array even
if they are not needed.
The only remaining thing that I can think of is to make a separate
data-type for every such needed half-dynamic pointer, so that aliasing
would be impossible:
type A_array ! or BC_array
real, allocatable, dimension(:) :: array
end type A_array ! or BC_array
type main_type
type(A_array), pointer :: A
type(BC_array), pointer :: B, C
end type main_type
this is a bit more restrictive and tedious, but it would work for me and
seems to solve both problem 1 and 2. Yet it still fails with LF95, for
reasons that escape me (also, with this compiler allocatable arrays
inside data-types are internally still treated as array pointers and so
cause aliasing issues which should not be there...).
As an illustration for the truly interested, attached is a test code
memtest.f90 and a pdf file of the memory allocation activity of the
program, obtained using the mpatrol library. Unfortunately this library
only works with Fortran compilers that use malloc for dynamic
allocation, which does not seem to be the case with the new Intel
compiler (and I really wanted to test it on this tricky issue :().
Besides, ifc does not implememt allocatable components yet... As you can
see, the program is full of unneccessary temporaries.
Is the stand-point of most people in the committee that compilers should
perform run-time checks for these kind of things? This can get tedious
too, for the compiler and the produced executable...Or is the view that
this is not really a problem (i.e. can be avoided by "better"
programming) prevalent?
Thanks,
Aleksandar
--
__________________________________
Aleksandar Donev
Complex Materials Theory Group (http://cherrypit.princeton.edu/)
Princeton Materials Institute & Program in Applied and Computational Mathematics
@ Princeton University
Address:
419 Bowen Hall, 70 Prospect Avenue
Princeton University
Princeton, NJ 08540-5211
E-mail: [log in to unmask]
WWW: http://atom.princeton.edu/donev
Phone: (609) 258-2775
Fax: (609) 258-6878
__________________________________
program memtest
real, allocatable, dimension(:) :: a, b, c
type allocatable_array
real, allocatable, dimension(:) :: array
end type allocatable_array
type(allocatable_array), pointer :: a_alloc,b_alloc,c_alloc
type A_array
real, allocatable, dimension(:) :: array
end type A_array
type B_array
real, allocatable, dimension(:) :: array
end type B_array
type C_array
real, allocatable, dimension(:) :: array
end type C_array
type(A_array), pointer :: a_A
type(B_array), pointer :: b_B
type(C_array), pointer :: c_C
type box_type
real, allocatable, dimension(:) :: a, b, c
end type box_type
type(box_type) :: box
integer :: n
write(*,*) "Enter n"
read(*,*) n
allocate(a(n),b(n),c(n))
allocate(a_alloc,b_alloc,c_alloc)
allocate(a_alloc%array(n),b_alloc%array(n),c_alloc%array(n))
allocate(a_A,b_B,c_C)
allocate(a_A%array(n),b_B%array(n),c_C%array(n))
a=b+c ! NO TEMPORARY
a_alloc%array=b_alloc%array+c_alloc%array ! TEMPORARY
a_A%array=b_B%array+c_C%array ! Requires NO TEMPORARY, but one IS created!?!
allocate(box%a(n),box%b(n),box%c(n))
box%a=box%b+box%c ! Requires NO TEMPORARY, but one IS created!?!
end program memtest
! EOF
|