Ranges
Formally we can think of a range as a map from an integer interval
0,...,N-1 into
some process dimension (ie, some dimension of a process grid).
Ranges are used to parametrize distributed arrays, and the
overall distributed loop.
In HPJava ranges are represented by objects of class Range.
The most common way to create one is to use the constructor for one of
the subclasses representing ranges with specific distribution
formats. A class hierarchy of ranges is given below:
The simple block distribution format implemented by BlockRange
was used directly in the matrix multiplication example.
The standard constructor for BlockRange has interface
public BlockRange(int N, Dimension d) {...}
As we saw earlier, a range x, of class BlockRange
yields distributed arrays distributed as in this example:
The Range subclass CyclicRange deals with
another distribution format from High Performance Fortran. The interval
is mapped to the process dimension in wraparound mode, as in this example
involving three processes:
The standard constructor for CyclicRange has interface
public CyclicRange(int N, Dimension d) {...}
Earlier we discussed arrays with sequential dimensions (for example the arrays
a and b in the original form of the matrix
multiplication). Not too surprisingly sequential dimensions also have
range objects associated with them. These are members of the subclass
CollapsedRange, which describe sequential, undistributed
dimensions of HPJava arrays. Constructors for CollapsedRange
objects are usually not called explicitly (although they can be).
Instead a CollapsedRange object is created implicitly every
time an array with a sequential dimension is created.
The Range subclass ExtBlockRange is
closely related to BlockRange. An instance
of ExtBlockRange has an identical set of locations
to a corresponding BlockRange object.
The difference is that when
an array is created with a dimension of type ExtBlockRange,
extra space is allocated round the edges of the locally held
segment of the array. These ghost extensions can be
used to cache local copies of elements held on neighboring processes.
This is very useful for certain patterns of update involving a
local stencil. We give a complete example on the next slide. Here
is a simplified example:
The elements shown in yellow represent locally cached copies of elements
properly belonging to adjacent processes (for the sake of definiteness
we assumed wraparound at the edges of the grid, but the exact interpretation
of the extra elements is entirely up to the program that initializes them.)
The standard constructors for ExtBlockRange are:
public ExtBlockRange(int N, Dimension d) {...}
public ExtBlockRange(int N, Dimension d, int w) {...}
public ExtBlockRange(int N, Dimension d, int w_lo, int w_hi) {...}
The first constructor adds extensions of width 1 to the low and
high end of the local segments (as above). The second adds extensions of
width w to both ends. The third allows extensions with
different widths at the two ends.
IrregRange is another generalization of BlockRange
where the lengths of the segments associated with each process along a
dimension can be specified independently by an array of lengths passed to
the constructor of the range.
Finally, any dimension of a process grid is represented as an object
of class Dimension, and Dimension
itself is a subclass of Range - namely a range with a single
location in each process. This means that it is
possible to declare an array with a single element in every process along
the dimension. This is most useful in multidimensional arrays, and
is especially common in multidimensional arrays where some other
dimensions are sequential. For example if we created an array by
Dimension x = p.dim(0) ;
float [[-,*]] a = new [[x, 5]] ;
it would have a distribution something like:
Note the interesting similarities and subtle differences between an
array created in this way and a one-dimensional array distributed blockwise.
HPJava is quite flexible and often allows several ways to represent
essentially similar data distributions. As above, instances
of the Dimension class are usually obtained from
a Procs object through the inquiry dim(),
rather than through a constructor.
Next:
Another Example - the Laplace Equation
|