The data mapping directives (see Section 5) and the layout directives (see Section 6) can also be used to describe the mapping and layout of dummy arguments.
The mapping of each such dummy argument may be related to the mapping of its associated actual argument in the calling main program or procedure (the ``caller'') in several different ways.
With the RANGE directive the user can be more specific about the possible mappings.
The ADAPTOR compiler will generate the code for the remapping in the called subprogram. So it is usually not necessary to provide an explicit interface for the called subprogram in the caller. This approach has been chosen for the following reasons:
Therefore it is not absolutely necessary to provide an explicit interface. Nevertheless, it is recommended for the following reasons:
Attention: Within local and serial routines (EXTRINSIC("LOCAL",...), EXTRINSIC("SERIAL",...)), the called routine will not do any remapping. In this case, an explicit interface is mandatory if a redistribution is necessary.
If the INHERIT attribute is specified for a dummy argument, the called subprogram must accept any mapping of the actual argument. The actual argument will not be redistributed. There must not be any other mapping directive (DISTRIBUTE or ALIGN).
The RANGE directive is used to restrict the possible mapping formats of the actual argument.
SUBROUTINE SUB (X) REAL X(:,:) !hpf$ INHERIT X !HFP$ RANGE X (block(),block()) (*,GEN_block())
The object in the RANGE directive must have the INHERIT attribute. The mapping of the actual argument must be a specialization of at least one of the format-clauses in the RANGE directive.
Attention: There is no runtime check to verify that the actual argument has really a certain mapping
REAL A(100, 100, 100) !hpf$ distribute A(block, *, CYCLIC) CALL SUB( A(:,,:,1) ) ! Conforming CALL SUB( A(:,,1,:) ) ! Nonconforming CALL SUB( A(1,,:,:) ) ! Nonconforming .... SUBROUTINE SUB(X) REAL A(:, :) !hpf$ INHERIT X !hpf$ RANGE X (block, *)
In the most situations, ADAPTOR will use copy-in and copy-out for array sections passed to subprograms. The only exception is given for inherited mappings.
REAL a(n,n) ... CALL sub (a(2:n:2,:),a(1:n:2,:)) ... SUBROUTINE sub (x, y) REAL x(:,:), y(:,:) !hpf$ distribute x(block(),block()) onto * !hpf$ INHERIT y ... END SUBROUTINE sub
The more underspecified a distribution is, the more general is the code.
SUBROUTINE sub (A1, A2, N) REAL A1(N), A2(N) !hpf$ distribute (block) :: A1, A2 A1 = A2 ! same distribution, no communication END SUBROUTINE sub
SUBROUTINE sub (A1, A2, N) REAL A1(N), A2(N) !hpf$ distribute (block) onto * :: A1, A2 A1 = A2 ! distribution can be different (communication) END SUBROUTINE sub
SUBROUTINE sub (A1, A2, N) REAL A1(N), A2(N) !hpf$ distribute (block) onto *:: A1 !hpf$ align (I) with A1(I) :: A2 A1 = A2 ! aligned, no communication END SUBROUTINE sub
The following example shows how the mechanism can be used to realize efficient code for different distributions.
integer, parameter :: N1=10, N2=2*N1, N3=4*N1, N4=8*N1 real, dimension (0:N1,0:N1) :: A1 real, dimension (0:N2,0:N3) :: A2 real, dimension (0:N3,0:N3) :: A3 real, dimension (0:N4,0:N4) :: A4 !hpf$ align A1(I,J) with A4(8*I,8*J) !hpf$ align A2(I,J) with A4(4*I,4*J) !hpf$ align A3(I,J) with A4(2*I,2*J) call SUB (A1, A2, N1) call SUB (A2, A3, N2) call SUB (A3, A4, N3) subroutine SUB (X, Y, N) real X(0:n,0:n), Y(0:2*n,0:2*n) !hpf$ distribute Y(block(),block()) onto * !hpf$ align X(i,j) with Y(2*i,2*j) ... end subroutine SUB
Due to the fact that this kind of directives could be combined and the new standard allows also underspecified mappings, we gave up this terminology and introduced a terminology based on underspecified mappings.