There are three main families of collective operation in Adlib: regular communications, reduction operations, and irregular communications. It also provides a few I/O operations.
The regular communications are exemplified by the operations remap(), writeHalo(), shift(), and cshift(), introduced in earlier sections. The first of these, remap(), is a very characteristic example. The remap() method takes two distributed array arguments--a source array and a destination. These two arrays must have the same size and shape6.2but they can have any, unrelated, distribution formats. The effect of the operation is to copy the values of the elements in the source array to the corresponding elements in the destination array, performing any communications necessary to do that. If the destination array has replicated mapping, the remap() operation will broadcast source values to all copies of the destination array elements.
The remap() method is a static member of the Adlib class.
Like most of the methods in Adlib, the remap() method is
overloaded to apply to various ranks and types of array:
The overloading with respect to rank
is slightly more problematic, because
there are infinitely many possible ranks, and for now the HPJava
language has no way to express that an argument can have arbitrary
rank. As currently implemented, we can summarize the available
remap() signatures in the notation:
#means a multiarray of arbitrary rank, with elements of type .
This notation is quite terse, and perhaps cryptic at first sight, but you will need to get used to it to follow the rest of this chapter. Bear in mind that one should mentally expand this kind of prototype into a series of signatures similar to the ones given above.
You may notice that this shorthand signature contains slightly less
information than the series given above, because it doesn't impose as a
compile-time constraint that source and destination arrays have
the same rank. But as a matter of fact it is a more accurate
reflection of the current implementation--although it is not possible
to define multiarray parameters of unspecified rank within the
HPJava language (i.e. there is no such type as
# in HPJava),
the translator provides a special hook that allows methods of ``externally
defined'' libraries--typically libraries written in standard Java--to
behave as if they had such parameters.
There are four preconditions to a call to remap():
If the second condition above is not satisfied an hpjava.adlib.schedule.RankMismatchException or an hpjava.adlib.schedule.ShapeMismatchException will be thrown. If the last condition is not satisfied an hpjava.adlib.schedule.InaccessibleException will be thrown.
Most of the functions in Adlib have a similar set of preconditions--all operations are called collectively with coherent arguments, input and output arrays should never overlap, and array arguments must always be fully contained in the active group. The last requirement is probably the easiest to overlook. Consider the example of section 3.4, Figure 3.18. An easy mistake would be to put the calls to remap() inside the following on construct. This is an error, because there is no guarantee that distribution groups of a and b are contained in the distribution group, p, of c (the function matmul is supposed to work for arguments with any, unrelated, distribution format). The Adlib library includes runtime checks for containment of arrays. If an argument is not fully contained in the APG, an exception occurs as described above.
So long as the rule on containment is observed, Adlib calls can
be made freely inside distributed control constructs, including
the parallel loop, overall.
If, for example, we want to ``skew''
an array--shift rows in the y direction by an amount
that depends on the x index--we can do something like
A prototype of the shift() function was given in section
2.4. In general we have the signatures:
). By design, shift() implements a simpler pattern of communication than general remap(). The alignment relation allows for a more efficient implementation. The library incorporates runtime checks on alignment relations between arguments, where these are required. If the arguments of shift() are not correctly aligned an hpjava.adlib.schedule.GroupMismatchException or an hpjava.adlib.schedule.MisalignmentException will be thrown.
The shift() operation does not copy values from source that would go past the edge of destination, and at the other extreme of the range elements of destination that are not targetted by elements from source are unchanged from their input value. The related operation cshift() is essentially identical to shift() except that it implements a circular shift, rather than an ``edge-off'' shift.
The function writeHalo() is applied to distributed arrays that have
ghost regions. It updates those regions. The simplest versions have
More general forms of writeHalo allow to specify
that only a subset of the available ghost area is to be updated, or
to select circular wraparound for updating ghost cells
at the extreme ends of the array:
Operation of writeHalo() is visualized in figure 6.1.
Finally we mention the function broacast(), which is actually a
simplified form of remap(). There are two signatures:
The second form of broadcast() just takes an ordinary Java value as the source. This value should be defined on the process or group of processes identified by root. It is broadcast to all members of the active process group. Technically this version is only useful if the source expression is incoherent--see section 5.4--but it is quite handy in practical codes.