next up previous contents
Next: Bibliography Up: Issues in Translation of Previous: Ranges   Contents

A DAD

Before ranges and groups can be put together to make a DAD we need to deal with one other detail. This is the issue of memory strides.

An array dummy argument may be matched with an array section in the calling program. So for a dummy the layout of elements in memory may be different to what would be expected for a general Fortran array. This problem is not specific to HPF--it is a feature of Fortran 90. In:

      REAL D(100, 100)
      ...
      CALL FOO(D(1, :))


      SUBROUTINE FOO(C)
      REAL C(:)
      ...
      END
the first dimension of D is most-rapidly-varying, so the stride in that dimension--the memory displacement between adjacent elements--is 1 word. The second dimension has a stride of 100 words. So the stride for the dummy argument C will also be 100. Fortran compilers typically take this into account by passing a dope vector for an array argument. For a rank-$r$ argument the dope vector contains the $r$ extents and the $r$ strides that describe the shape of the array and its memory layout [2]. The procedure code uses the stride information from the dope vector when resolving array references.

In our DAD the extent information fits naturally in the Range objects. We find it convenient to keep the memory stride information separate. It seems useful to allow range objects to be shared by arrays that have the same mapping in particular dimensions, although they may have different overall shape and memory layout.

The upshot is that the DAD for a rank-$r$ array will contain:

Figure 9 gives an interface for the DAD class. Here Map is a small structure that bundles a range with a stride:
    struct Map {
    public :
        Map(Range _range, const int _stride) ;

        Range range ;
        int stride ;
    } ;

Figure 9: Interface of the DAD class.
\begin{figure}\small\begin{verbatim}struct DAD {
DAD(const int _rank, const ...
... ;int str(const int r) const ;
...
} ;\end{verbatim}\normalsize\end{figure}

With this DAD, we can finally give a translation of the second example in section 1. Source and translation is given in Figure 10. To fully appreciate how this translation works, we need to see how the calling program sets up the DAD. For this we revist the four examples in Figure 2. Sources and translations are given in Figures 11 through 14.

The translations in Figures 11 and 12 are fairly self-explanatory. A DAD is set up describing array b. This contains a group object describing p (the conversion from Procs to Group is implicitly used) and and a map object containing the range x and stride 1. A pointer to the DAD is passed to the procedure, together with the pointer to the elements.

Figure 13 is a little more complicated. We again create a range parameterizing the 100-element array b. In mechanically translated code we might go on to set up a DAD describing the whole of B, but for simplicity we skip this stage here. We only set up a DAD describing the strided section of b. This involves using the subrng() method on Range to create a new range object representing a subrange. The subrange has stride 2. When the the procedure init() calls the block() method on this object, it will return appropriately adjusted values for subscript and global index bases and steps.

Figure 14 is more complicated again. To deal with the scalar subscript it uses the location() method. This takes the global subscript as argument and returns a Location structure, which has fields:

    struct Location {
      int crd ;
      int sub ;
      ...
    } ;
These define the corresponding process coordinate and local subscript. In some sense location() is the dual method to block()--block() takes a process coordinate and returns a range of indices (and local subscripts)--location takes an index and returns a coordinate (and a local subscript)8. Note the memory stride for the second dimension, x.volume(), goes into the Map object, and the base address passed to the procedure is offset in memory by an amount determined by the scalar subscript. Of course the group in the DAD was suitably restricted.

Figure 10: C++ translation of HPF program with inheritted mapping.
\begin{figure}\textbf{SOURCE:}
\small\begin{verbatim}SUBROUTINE INIT(A)REA...
..._bas + b.sub_stp * l)] = 1.0 * i ;
}
}
}\end{verbatim}\normalsize\end{figure}

Figure 11: Translation of first example from Figure 2.
\begin{figure}\textbf{SOURCE:}
\small\begin{verbatim}!HPF$ PROCESSORS P(4)...
...b, &dad);... do some global finalization\end{verbatim}\normalsize\end{figure}

Figure 12: Translation of second example from Figure 2.
\begin{figure}\textbf{SOURCE:}
\small\begin{verbatim}!HPF$ PROCESSORS P(4)...
...b, &dad);... do some global finalization\end{verbatim}\normalsize\end{figure}

Figure 13: Translation of third example from Figure 2.
\begin{figure}\textbf{SOURCE:}
\small\begin{verbatim}!HPF$ PROCESSORS P(4)...
...b, &dad);... do some global finalization\end{verbatim}\normalsize\end{figure}

Figure 14: Translation of fourth example from Figure 2.
\begin{figure}\textbf{SOURCE:}
\small\begin{verbatim}!HPF$ PROCESSORS Q(2, 2)...
...b, &dad);... do some global finalization\end{verbatim}\normalsize\end{figure}


next up previous contents
Next: Bibliography Up: Issues in Translation of Previous: Ranges   Contents
Bryan Carpenter 2002-07-12