A variable with the POINTER or ALLOCATABLE attribute may appear
as an alignee
in an ALIGN directive or as a distributee in a DISTRIBUTE
directive. Such directives do not take effect immediately, however; they
take effect each time the array is allocated by an ALLOCATE statement,
rather than on entry to the scoping unit.
The values of all specification expressions in such a directive
are determined once on entry to the scoping unit
and may be used multiple times (or not at all).
For example:
Note that it would have been incorrect in the MILLARD_FILLMORE example
to perform the two ALLOCATE statements in the opposite order.
In general, when an object X is created it may be aligned to another
object Y only if Y has already been created or allocated.
The following example illustrates several related cases.
If an ALLOCATE statement is immediately followed by REDISTRIBUTE
and/or REALIGN directives,
the meaning in principle is that the array is first created
with the statically declared alignment, then immediately remapped.
In practice there is an obvious optimization: create the array
in the processors to which it is about to be remapped, in a single
step. HPF implementors are strongly encouraged to implement this
optimization and HPF programmers are encouraged to rely upon it.
Here is an example:
An array pointer may be used in REALIGN and REDISTRIBUTE as an
alignee, align-target, or distributee
if and only if it is currently
associated with a whole array, not an array section. One may remap an object
by using a pointer as an alignee or distributee only if the
object was created by ALLOCATE but is not an ALLOCATABLE array.
Any directive that remaps an object constitutes an assertion on the
part of the programmer that the remainder of program execution would
be unaffected if all pointers associated with any portion of the
object were instantly to acquire undefined pointer association
status, except for the one pointer, if any, used to indicate the
object in the remapping directive.
When an array is allocated, it will be aligned to an existing template
if there is an explicit ALIGN directive for the allocatable
variable. If there is no explicit ALIGN directive, then the array
will be ultimately aligned with itself. It is forbidden for any
other object to be ultimately aligned to an array at the time the
array becomes undefined by reason of deallocation. All this applies
regardless of whether the name originally used in the ALLOCATE
statement when the array was created had the ALLOCATABLE attribute or
the POINTER attribute.
SUBROUTINE MILLARD_FILLMORE(N,M)
REAL, ALLOCATABLE, DIMENSION(:) :: A, B
!HPF$ DISTRIBUTE A(BLOCK(M*2))
N = 43
M = 91
ALLOCATE(A(27))
ALLOCATE(B(13))
...
The values of the expressions N and M*2
on entry to the subprogram are conceptually retained by the
ALIGN and DISTRIBUTE directives for later use at allocation time.
When the array A is allocated, it is distributed with a block size
equal to the retained value of M*2, not the value 182.
When the array B is allocated, it is aligned relative to A
according to the retained value of N, not its new value 43.
SUBROUTINE WARREN_HARDING(P,Q)
REAL P(:)
REAL Q(:)
REAL R(SIZE(Q))
REAL, ALLOCATABLE :: S(:),T(:)
!HPF$ ALIGN Q(I) WITH *T(I) !Nonconforming
!HPF$ ALIGN S(I) WITH T(I)
ALLOCATE(S(SIZE(Q))) !Nonconforming
ALLOCATE(T(SIZE(Q)))
The ALIGN directives are not HPF-conforming because the array T
has not yet been allocated at the time that the various alignments
must take place. The four cases differ slightly in their details.
The arrays P and Q already exist on entry to the
subroutine, but because T is not yet allocated, one cannot
correctly prescribe the alignment of P or describe the
alignment of Q relative to T. (See Section
for a discussion of prescriptive and descriptive directives.)
The array R is created on subroutine entry and its size
can correctly depend on the SIZE of Q, but the alignment
of R cannot be specified in terms of the alignment of T
any more than its size can be specified in terms of the size of T.
It is permitted to have an alignment directive for S
in terms of T, because the alignment action does not take place
until S is allocated; however, the first ALLOCATE
statement is nonconforming because S needs to be aligned
but at that point in time T is still unallocated.
REAL,ALLOCATABLE(:,:) :: TINKER, EVERS
!HPF$ DISTRIBUTE(BLOCK),DYNAMIC :: CHANCE
...
READ 6,M,N
ALLOCATE(TINKER(N*M,N*M))
!HPF$ REALIGN EVERS(:,:) WITH TINKER(M::M,1::M)
ALLOCATE(CHANCE(10000))
!HPF$ REDISTRIBUTE CHANCE(CYCLIC)
While CHANCE is by default always allocated with a BLOCK
distribution, it should be possible for a compiler to notice that it will
immediately be remapped to a CYCLIC distribution. Similar remarks
apply to TINKER and EVERS. (Note that EVERS
is mapped in a thinly-spread-out manner onto TINKER;
adjacent elements of EVERS are mapped to elements of
TINKER separated by a stride M. This thinly-spread-out
mapping is put in the lower left corner of TINKER,
because EVERS(1,1) is mapped to TINKER(M,1).)
Next: PROCESSORS Directive
Up: Data Alignment and
Previous: DYNAMIC Directive