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-directive is ALIGN alignee align-directive-stuff H314 align-directive-stuff is ( align-source-list ) align-with-clause H315 align-attribute-stuff is [ ( align-source-list ) ] align-with-clause H316 alignee is object-name H317 align-source is :
H318 align-dummy is scalar-int-variable
extensions (see Section 8): mapping of derived type components (relaxes constraint 1) and mapping of pointers and targets (relaxes constraints 3 and 4). (End of advice to users.)
Note that the possibility of an ALIGN directive of the form
is covered by syntax rule H301 for a combined-directive.!HPF$ ALIGN align-attribute-stuff :: alignee-list
The statement form of an ALIGN directive may be considered an abbreviation of an attributed form hat happens to mention only one alignee:
is equivalent to!HPF$ ALIGN alignee ( align-source-list ) WITH align-spec
!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
means!HPF$ ALIGN WITH B :: A1, A2, A3
which in turn means the same as!HPF$ ALIGN (:,:) WITH B(:,:) :: A1, A2, A3
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.!HPF$ ALIGN A1(:,:) WITH B(:,:) !HPF$ ALIGN A2(:,:) WITH B(:,:) !HPF$ ALIGN A3(:,:) WITH B(:,:)
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-clause is WITH align-spec H320 align-spec is align-target [ ( align-subscript-list ) ]
or * align-target [ ( align-subscript-list ) ]
H321 align-target is object-name
H322 align-subscript is int-expr
H323 align-subscript-use is [ [ int-level-two-expr ] add-op ]
or align-subscript-use add-op int-add-operand
H324 align-add-operand is [ int-add-operand * ] align-primary
or align-add-operand * int-mult-operand
H325 align-primary is align-dummy
or ( align-subscript-use )
H326 int-add-operand is add-operand H327 int-mult-operand is mult-operand H328 int-level-two-expr is 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).
extensions (see Section 8): mapping of derived type components (relaxes constraint 1), mapping of pointers (relaxes constraint 3) and remapping of data objects (relaxes constraints 4 and 5). (End of advice to users.)
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
J J+1 3-K 2*M N*M 100-3*M -J +J -K-3 M+2**3 M+N -(4*7+IOR(6,9))*K-(13-5/3) M*2 N*(M-N) 2*(J+1) 5-K+3 10000-M*3 2*(3*(K-1)+13)-100
The following expressions are not valid align-subscript-use expressions:
J+J J-J 3*K-2*K M*(N-M) 2*J-3*J+J 2*(3*(K-1)+13)-K J*J J+K 3/K 2**M M*K K-3*M K-J IOR(J,1) -K/3 M*(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
must be true. (This is entirely analogous to the treatment of array assignment.)max(0,UA-LA+1) = max(0,[(UT-LT+1)/ST])
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,
may be transformed into its equivalent!HPF$ ALIGN A(:,*,K,:,:,*) WITH B(31:,:,K+3,20:100:3)
with the attached requirements!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)
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,means that a copy of A is aligned with every column of D, because it is conceptually equivalent to!HPF$ ALIGN A(:) WITH D(:,*)for every legitimate index j, align A(:) with D(:,j)just asis conceptually equivalent to!HPF$ ALIGN A(:,*) WITH D(:)for every legitimate index j, align A(:,j) with D(:)Note, however, that while HPF syntax allowsto be written in the alternate form!HPF$ ALIGN A(:,*) WITH D(:)it does not allow!HPF$ ALIGN A(:,j) WITH D(:)to be written in the alternate form!HPF$ ALIGN A(:) WITH D(:,*)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).!HPF$ ALIGN A(:) WITH D(:,J)
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