[ HPF Home | Versions | Compilers | Projects | Publications | Applications | Benchmarks | Events | Contact ] |
If a RESIDENT directive applies to procedure reference, then the assertion is more subtle.
!HPF$ RESIDENT( A(I), B ) A(I) = F( A(I), B(LO:HI) )
The directive declares all variable refences in the statement (including the actual arguments) to be local to the current ON processor set, and that F itself does not reference or update any nonlocal variables.
REAL FUNCTION F( X, Y ) USE MODULE_DEFINING_A REAL X, Y(:), B(I) !HPF$ INHERIT Y !HPF$ ALIGN B(:) WITH Y(:) INTEGER I Z = 0.0 DO I = 1, SIZE(Y) Z = Z + A(I)*X + B(I)*Y(I) END DO F=Z END FUNCTION
Assume A is defined as a distributed, global array in module MODULE_DEFINING_A. What should the RESIDENT clause mean regarding operations in F? The expression A(I) in the RESIDENT directive might reasonably mean references only to the array A. Note that the A in the caller may be local, the same global array as the A in F (if the caller used MODULE_DEFINING_A), or a different global array (if the caller used a different module). Perhaps a limiting cvase is array B. The array B in function F is local, and thus different from the caller; however, because of the restrictions on ON clauses it is certain that the local B will be mapped to the ON processor set. Thus, the RESIDENT assertion is trivially true. To further confuse matters, RESIDENT variables might seem to apply to dummy arguments that become associated with those variables. Unfortunately, this implies that the lexical expression B in the caller refers to the lexical expression Y in F, which stretches the definition of "lexical" beyond the breaking point. For all these reasons, it was decided to limit the meaning of named variables in RESIDENT clauses to the lexical scope of the directive. (End of rationale.)
!HPF$ RESIDENT A(I) = F( A(I), B(LO:HI) )
The directive declares all variable refences in the statement (including the actual arguments) to be local to the current ON processor set, and that F itself does not reference or update any nonlocal variables.
The other forms of RESIDENT provide information that could be propagated interprocedurally. For example, if the actual argument to a subprogram is asserted to be RESIDENT and is passed transcriptively, then anything that is aligned to it in the callee will also be RESIDENT. If the information is not propagated, the only result will be less optimization. (End of advice to implementors.)
Locality information is particularly critical interprocedurally. Here, the RESIDENT directive without a res-object-list can be used to good advantage. Consider the following extension of the block-structured example from Section 9.2.4:
!HPF$ PROCESSORS PROCS(NP) !HPF DISTRIBUTE X(BLOCK) ONTO PROCS ! Compute ILO(IP) = lower bound on PROCS(IP) ! Compute IHI(IP) = upper bound on PROCS(IP) DONE = .FALSE. DO WHILE (.NOT. DONE) !HPF$ INDEPENDENT DO IP = 1, NP !HPF$ ON (PROCS(IP)), RESIDENT CALL SOLVE_SUBDOMAIN( IP, X(ILO(IP):IHI(IP)) ) END DO !HPF$ ON HOME(X) BEGIN CALL SOLVE_BOUNDARIES( X, ILO(1:NP), IHI(1:NP) ) !HPF$ RESIDENT DONE = CONVERGENCE_TEST( X, ILO(1:NP), IHI(1:NP) ) !HPF$ END ON END DO
Recall that the INDEPENDENT IP loop performs a computation on each subdomain's interior, where a subdomain is mapped to a particular processor. The first RESIDENT clause additionally informs the compiler that no subdomain uses data from another processor. Without this information, the compiler would have to assume a worst-case scenario in which each subdomain performed its updates based on non-local read-only data. Any nonlocal data could not be written by another processor without violating the tt INDEPENDENT directive; however, if the data were not updated (for example, a large lookup table) it could be stored remotely. Particularly on nonshared-memory machines, access to this remote data would be difficult. The RESIDENT clause ensures that this possibility need not be considered. All data required by SOLVE_SUBDOMAIN is stored locally. The second RESIDENT clause asserts that all data for CONVERGENCE_TEST is stored on the same processors that store X. The same cannot be said for SOLVE_BOUNDARIES, which does not fall in the scope of the RESIDENT directive. For example, there might be a processors arrangement other than PROCS with necessary data. Accessing this data might well cause a bottleneck in the computation as described above.
Again, note the usefulness of RESIDENT clauses in giving the compiler information. Few compilers would be able to unravel nontrivial assignments to ILO and IHI, and no current compiler would even attempt to understand the comments in the above code fragment. End of advice to programmers.
©2000-2006 Rice University | [ Contact Us | HiPerSoft | Computer Science ] |