Next: Online Scheduled Routing
Up: Operator Implementations
Previous: Implementation Types
The compiler can also create meta-implementations out of existing
implementations to support operators with data-dependent arguments.
There are two basic ways to do this:
- A runtime-parallel implementation simply takes all the possible
values of a runtime operator's argument, and instantiates a separate
set of streams for each one. At run time the COP code uses the streams
that correspond to the selected runtime argument. In this case, the
compiler temporarily modifies the operator to have the appropriate compile-time
arguments (one at a time), calls the stream function, and adds all
the resulting streams into the set; then, when generating the code, the
compiler simply creates a frontend function to choose which streams to use.
- For a runtime-subphase implementation, a runtime
operator is decomposed to multiple compile-time subphases, each holding one
compile-time-valued instance of the operator as well as any other
operators present in the phase. Each subphase, accordingly,
is the same except for an operand value in the operator in question.
Doing this requires a separate phase compilation for
each subphase; the implementation's stream function is called once for
each compile-time flavor. This option is impractical when there are
other sequentially-preceding operators in the phase, since before this
operator's load function is called it will not be known what subphase to issue.
If one were picked at random it would be necessary to reload it at
that point, so it makes more sense to load a separate phase.
Notice that the multiple-phase meta-implementation, in particular,
may cause an explosion of possible phases that need to be stored in the
processor's memory; the number of subphases accumulates as the product
of the runtime value range of each operator's operand(s). For just
two operators, each with one operand that can take on any of 256 values
(for example), there are already 64K possible subphases for one phase.
Accordingly,
the compiler can be given a limit on the number of
phases per node, so as not to overwhelm the node memory with phase data.
Choosing which subphase to load is fairly straightforward. Each load
function is responsible for taking its argument and using it to
generating an operator index (in the range 0...k-1 , where k
is the number of subphases associated with the operator)
and storing it in memory. Once all
the operator indices have been generated for a phase, the last load
function invoked aggregates them into a single subphase index
used to pick one subphase from the set and issue the router command to
start running that subphase.
Next: Online Scheduled Routing
Up: Operator Implementations
Previous: Implementation Types
Back to Chris Metcalf's home page