Download Sequoia++ User Manual

Transcript
run on two arrays, storing the result in the second array argument. The final result is stored back at the
parent memroy level.
The reducearg need not be an entire array. In the example the reducearg shown above reduces the entire
matrix c into the final matrix c. The reduction also can be done on independent sub-blocks of the matrix c
by using array blocking to specify sub-blocks of the matrix. Array blocking is described in Section 5.6.
5.5
Task Calls
There are a few rules of thumb for getting the best performance and portability from tasks:
• The best performance is achieved if only task calls are placed in the parallel control constructs.
• For maximum portability task calls should be generic: they should not name which variant of the task
is to be called. The variant is specified in the mapping file.
• Tasks should be designed to break big problems into smaller problems recursively if that is appropriate
to the problem being solved. Thus the inner task variant will typically call the same task (with no
variant specified). This recursive structure will be mapped by the compiler on to the memory hierarchy
of the machine, with as many instances of the inner task as needed to cover the number of levels of
the target machine.
Note that tasks can only be called after they have been declared; forward declarations can be used if
necessary.
5.5.1
Entrypoints and Callsites
If a task is called from outside of Sequoia (for example calling a task from main() in a C program), that
instance of the task must be labelled with an entrypoint. The entrypoint construct is described in Section 8.3.
When a task calls another task an entrypoint is not used, instead one defines a callsite inside the control
block of the instance of the calling task (see Section 8.2).
5.6
Array Blocking
Array blocking allows the programmer to partition an array into smaller arrays. In combination with one
of the Sequoia control constructs a programmer can pass the different parts of the array to different task
instances. Consider again the matrix multiplication example:
// a, b, and c are two dimensional arrays
mappar( int i = 0 : M/mBlock , int j = 0 : N/nBlock )
mapseq( int k = 0 : P/pBlock )
matrixmult(a[i*mBlock;mBlock][k*pBlock;pBlock],
b[k*pBlock;pBlock][j*nBlock;nBlock],
c[i*mBlock;mBlock][j*nBlock;nBlock]);
Each task is passed a portion of each of arrays a, b, and c. The task either recursively subdivides its
portions of the arrays in further task calls (for an inner task call) or performs an actual matrix multiplication
(in a leaf task call). Notice that each dimension of the array has its own pair of brackets [...]. Arrays must
always be fully indexed, meaning that a n-dimensional array must always be used with all n dimensions.
Array blocking has two arguments per dimension. The first argument describes the index where the block
begins, and the second argument specifies the number of elements. For example, for the a matrix in the x
dimension, the partition passed to the i-th task consists of mBlock elements beginning at index i ∗ mBlock.
For the y dimension pBlock elements are taken beginning at k ∗ pBlock.
Note that many different parallel tasks (all with different values of j) are passed the same sub-array of a.
Because a is declared to be an in (read-only) parameter it presents no problem for multiple tasks to share
the same portion of a. However, any argument annotated out or inout can only be passed to a single parallel
task as it is undefined what occurs if multiple parallel tasks attempt to write the same output location. As
discussed previously, this requirement is not currently checked by the Sequoia compiler.
13