next up previous contents
Next: Allocatable Arrays and Pointers Up: Data Mapping Previous: The DISTRIBUTE Directive

The ALIGN Directive

 

The ALIGN directive is used to specify that certain data objects are to be mapped in the same way as certain other data objects. Operations between aligned data objects are likely to be more efficient than operations between data objects that are not known to be aligned (because two objects that are aligned are intended to be mapped to the same abstract processor). The ALIGN directive is designed to make it particularly easy to specify explicit mappings for all the elements of an array at once. While objects can be aligned in some cases through careful use of matching DISTRIBUTE directives, ALIGN is more general and frequently more convenient.

The ALIGN directive may appear only in the specification-part of a scoping unit and can contain only a specification-expr as a subscript or in a subscript-triplet.

The syntax of ALIGN is as follows:

H313 align-directiveis ALIGN alignee align-directive-stuff
H314 align-directive-stuffis ( align-source-list ) align-with-clause
H315 align-attribute-stuffis [ ( align-source-list ) ] align-with-clause
H316 aligneeis object-name
H317 align-source is :
or *
or align-dummy
H318 align-dummyis scalar-int-variable

Note that the possibility of an ALIGN directive of the form

!HPF$ ALIGN align-attribute-stuff :: alignee-list
is covered by syntax rule H301 for a combined-directive.

The statement form of an ALIGN directive may be considered an abbreviation of an attributed form hat happens to mention only one alignee:

!HPF$ ALIGN alignee ( align-source-list ) WITH align-spec
is equivalent to
!HPF$ ALIGN ( align-source-list ) WITH align-spec :: alignee

If the align-source-list is omitted from the attributed form and the alignees are not scalar, the align-source-list is assumed to consist of a parenthesized list of ":" entries, equal in number to the rank of the alignees. Similarly, if the align-subscript-list is omitted from the align-spec in either form, it is assumed to consist of a parenthesized list of ":" entries, equal in number to the rank of the align-target. So the directive

!HPF$ ALIGN WITH B :: A1, A2, A3
means
!HPF$ ALIGN (:,:) WITH B(:,:) :: A1, A2, A3
which in turn means the same as
!HPF$ ALIGN A1(:,:) WITH B(:,:)
!HPF$ ALIGN A2(:,:) WITH B(:,:)
!HPF$ ALIGN A3(:,:) WITH B(:,:)
because an attributed-form directive that mentions more than one alignee is equivalent to a series of identical directives, one for each alignee; all alignees must have the same rank. With this understanding, we will assume below, for the sake of simplifying the description, that an ALIGN directive has a single alignee.

Each align-source corresponds to one axis of the alignee, and is specified as either ``:'' or ``*'' or a dummy variable:

The WITH clause of an ALIGN has the following syntax:

H319 align-with-clauseis WITH align-spec
H320 align-specis align-target [ ( align-subscript-list ) ]
or * align-target [ ( align-subscript-list ) ]
H321 align-targetis object-name
or template-name
H322 align-subscriptis int-expr
or align-subscript-use
or subscript-triplet
or *
H323 align-subscript-useis [ [ int-level-two-expr ] add-op ]
or align-subscript-use add-op int-add-operand
H324 align-add-operandis [ int-add-operand * ] align-primary
or align-add-operand * int-mult-operand
H325 align-primaryis align-dummy
or ( align-subscript-use )
H326 int-add-operandis add-operand
H327 int-mult-operandis mult-operand
H328 int-level-two-expris level-2-expr

The full syntax is given here for completeness. However, some of the forms are discussed only in Section 4. These ``interprocedural'' forms are those using the second option of rule H320 (containing the * form).

The syntax rules for an align-subscript-use take account of operator precedence issues, but the basic idea is simple: an align-subscript-use is intended to be a linear (more precisely: affine) function of a single occurrence of an align-dummy.

For example, the following align-subscript-use expressions are valid, assuming that each of J, K, and M is an align-dummy and N is not an align-dummy:

JJ+13-K2*MN*M100-3*M
-J+J-K-3M+2**3M+N-(4*7+IOR(6,9))*K-(13-5/3)
M*2N*(M-N)2*(J+1)5-K+310000-M*32*(3*(K-1)+13)-100

The following expressions are not valid align-subscript-use expressions:

J+JJ-J3*K-2*KM*(N-M)2*J-3*J+J2*(3*(K-1)+13)-K
J*JJ+K3/K2**MM*KK-3*M
K-JIOR(J,1)-K/3M*(2+M)M*(M-N)2**(2*J-3*J+J)

The align-spec must contain exactly as many subscript-triplets as the number of colons (``:'') appearing in the align-source-list. These are matched up in corresponding left-to-right order, ignoring, for this purpose, any align-source that is not a colon and any align-subscript that is not a subscript-triplet. Consider a dimension of the alignee for which a colon appears as an align-source and let the lower and upper bounds of that dimension be LA and UA. Let the corresponding subscript triplet be LT:UT:ST or its equivalent. Then the colon could be replaced by a new, as-yet-unused dummy variable, say J, and the subscript triplet by the expression (J-LA)*ST+LT without affecting the mapping specified by the directive. However, the colon form additionaly requires that the axes must conform, which means that

max(0,UA-LA+1) = max(0,[(UT-LT+1)/ST])
must be true. (This is entirely analogous to the treatment of array assignment.)

To simplify the remainder of the discussion, we assume that every colon in the align-source-list has been replaced by new dummy variables in exactly the fashion just described, and that every ``*'' in the align-source-list has likewise been replaced by an otherwise unused dummy variable. For example,

!HPF$ ALIGN A(:,*,K,:,:,*) WITH B(31:,:,K+3,20:100:3)
may be transformed into its equivalent
!HPF$ ALIGN A(I,J,K,L,M,N) WITH B(I-LBOUND(A,1)+31,       &
!HPF$            L-LBOUND(A,4)+LBOUND(B,2),K+3,(M-LBOUND(A,5))*3+20)
with the attached requirements
SIZE(A,1) .EQ. UBOUND(B,1)-30
SIZE(A,4) .EQ SIZE(B,2)
SIZE(A,5) .EQ. (100-20+3)/3

Thus we need consider further only the case where every align-source is a dummy variable and no align-subscript is a subscript triplet.

Each dummy variable is considered to range over all valid index values for the corresponding dimension of the alignee. Every combination of possible values for the index variables selects an element of the alignee. The align-spec indicates a corresponding element (or section) of the align-target with which that element of the alignee should be aligned; this indication may be a function of the index values, but the nature of this function is syntactically restricted (as discussed above) to linear (precisely: affine) functions in order to limit the complexity of the implementation. Each align-dummy variable may appear at most once in the align-spec and only in certain rigidly prescribed contexts. The result is that each align-subscript expression may contain at most one align-dummy variable and the expression is constrained to be a linear function of that variable. (therefore skew alignments are not possible.)

An asterisk "*" as an align-subscript indicates a replicated representation. each element of the alignee is aligned with every position along that axis of the align-target.

Rationale. It may seem strange to use "*" to mean both collapsing and replication; the rationale is that "*" always stands conceptually for a dummy variable that appears nowhere else in the statement and ranges over the set of indices for the indicated dimension. Thus, for example,
!HPF$ ALIGN A(:) WITH D(:,*)
means that a copy of A is aligned with every column of D, because it is conceptually equivalent to
for every legitimate index j, align A(:) with D(:,j)
just as
!HPF$ ALIGN A(:,*) WITH D(:)
is conceptually equivalent to
for every legitimate index j, align A(:,j) with D(:)
Note, however, that while HPF syntax allows
!HPF$ ALIGN A(:,*) WITH D(:)
to be written in the alternate form
!HPF$ ALIGN A(:,j) WITH D(:)
it does not allow
!HPF$ ALIGN A(:) WITH D(:,*)
to be written in the alternate form
!HPF$ ALIGN A(:) WITH D(:,J)
because that has another meaning (only a variable appearing in the align-source-list following the alignee is understood to be an align-dummy, so the current value of the variable J is used, thus aligning A with a single column of D).

Replication allows an optimizing compiler to arrange to read whichever copy is closest. (Of course, when a replicated data object is written, all copies must be updated, not just one copy.) Replicated representations are very useful for small lookup tables, where it is much faster to have a copy in each phsical processor but without giving it an extra dimension that is logically unnecessary to the algorithm. (End of rationale.)

By applying the transformations given above, all cases of an align-subscript may be conceptually reduced to either an int-expr (not involving an align-dummy) or an align-subscript-use, and the align-source-list may then be evaluated for any specific combination of values for the align-dummy variables simply by evaluating each align-subscript as an expression. The resulting subscript values must be legitimate subscripts for the align-target. (This implies that the alignee is not allowed to "wrap around" or "extend past the edges" of an align-target.) The selected element of the alignee is then considered to be aligned with the indicated element of the align-target; more precisely, the selected element of the alignee is considered to be ultimately aligned with the same object with which the indicated element of the align-target is currently ultimately aligned (possibly itself).

More examples of ALIGN directives:

INTEGER D1(N)
LOGICAL D2(N,N)
REAL, DIMENSION(N,N)::X,A,B,C,AR1,AR2A,P,Q,R,S
!HPF$ ALIGN X(:,*) WITH D1(:)
!HPF$ ALIGN (:,*) WITH D1:: A,B,C,AR1,AR2A
!HPF$ ALIGN WITH D2:: P,Q,R,S

Note that, in a alignee-list, the alignees must all have the same rank but need not all have the same shape; the extents need match only for dimensions that correspond to colons in the align-source-list. This turns out to be an extremely important convenience; one of the most common cases in current practice is aligning arrays that match in distributed (``parallel'') dimensions but may differ in collapsed (``on-processor'') dimensions:

      REAL A(3,N), B(4,N), C(43,N), Q(N)
!HPF$ DISTRIBUTE Q(BLOCK)
!HPF$ ALIGN (*,:) WITH Q:: A,B,C

Here there are processors (perhaps N of them) and arrays of different sizes (3, 4, 43) within each processor are required. As far as HPF is concerned, the numbers 3, 4, and 43 may be different, because those axes will be collapsed. Thus array elements with indices differing only along that axis will all be aligned with the same element of Q (and thus be specified as residing in the same processor).

In the following examples, each directive in a group means the same thing, assuming that corresponding axis upper and lower bounds match:

!Second axis of X is collapsed
!HPF$ ALIGN X(:,*) WITH D1(:)
!HPF$ ALIGN X(J,*) WITH D1(J)
!HPF$ ALIGN X(J,K) WITH D1(J)

!Replicated representation along second axis of D3
!HPF$ ALIGN X(:,:) WITH D3(:,*,:)
!HPF$ ALIGN X(J,K) WITH D3(J,*,K)

!Transposing two axes
!HPF$ ALIGN X(J,K) WITH D2(K,J)
!HPF$ ALIGN X(J,:) WITH D2(:,J)
!HPF$ ALIGN X(:,K) WITH D2(K,:)
!But there isn't any way to get rid of *both* index variables;
! the subscript-triplet syntax alone cannot express transposition.

!Reversing both axes
!HPF$ ALIGN X(J,K) WITH D2(M-J+1,N-K+1)
!HPF$ ALIGN X(:,:) WITH D2(M:1:-1,N:1:-1)

!Simple case
!HPF$ ALIGN X(J,K) WITH D2(J,K)
!HPF$ ALIGN X(:,:) WITH D2(:,:)
!HPF$ ALIGN (J,K) WITH D2(J,K):: X
!HPF$ ALIGN (:,:) WITH D2(:,:):: X
!HPF$ ALIGN WITH D2:: X


next up previous contents
Next: Allocatable Arrays and Pointers Up: Data Mapping Previous: The DISTRIBUTE Directive