Parallel programming involves finding the potential parallelism in an
application, choosing an algorithm, and mapping it to the architecture
at hand. Since a typical algorithm has much more potential parallelism
than any single architecture can effectively exploit, we usually
program the parallelism that the available control constructs easily
express and that the given architecture efficiently exploits. This
approach produces programs that exhibit much less parallelism than the
original algorithm and whose performance depends entirely on the
underlying architecture. To port such a program to a new architecture,
we must rewrite the program to remove any ineffective parallelism and
to recover any lost parallelism appropriate for the new machine.

In this paper we show how to adapt a parallel program to different
architectures using control abstraction. With control abstraction we
can define and use a rich variety of control constructs to represent an
algorithm's potential parallelism. Since control abstraction separates
the definition of a construct from its implementation, a construct may
have several different implementations, each exploiting a different
subset of the parallelism admitted by the construct. By selecting an
implementation for each control construct using annotations, we can
vary the parallelism we choose to exploit without otherwise changing
the source code. This approach produces programs that exhibit most of,
if not all, the potential parallelism in an algorithm, and whose
performance can be tuned for a specific architecture simply by choosing
among the various implementations for the control constructs in use.