Parallel Action

Process instantiation

The operator # is the standard operator for process instantiation in Eden. Similar
to applying a function f to an argument x (f x), it instantiates
a process for f with the argument x (process f # x). The computation is
the same from a denotational point of view. The operational semantics,
however, is different because the operation is executed remotely. If
you prefer to expose the side effects of such an operation explicitly with the
IO-Monad wrapped in the parallel action monad, you can use function instantiate
(p # x = runPA (instantiate p x)). It is non-trivial to instantiate
a list of processes such that all instantiations take place immediately. Therefore Eden
provides function spawn which wraps this commonly used pattern.

The Eden runtime system handles process placementfor the basic instantiation functions.
In the default setting, process placement is done round robin,
where the distribution is decided locally by each machine. The runtime option qrnd
enables random process placement. Eden further offers functions instantiateAt and
spawnAt with an additional placement parameter. instantiateAt i instantiates the
process at machine i mod noPe for a positive i and instantiateAt 0 = instantiate.
This is similar for spawnAt.

All instantiation functions are also provided in versions which take functions instead
of process abstractions as parameters. In this case, the process abstractions are
implicitly created prior to instantiation. The function version of ,
the names of other instantiation functions of this kind contain an F.

Instantiates a list of process abstractions on remote machines
with corresponding inputs of type a and returns the processes
outputs, each of type b. The i-th process is supplied with the
i-th input generating the i-th output.
The number of processes (= length of output list) is determined by
the length of the shorter input list (thus one list may be infinite).

Instantiates processes defined by the given list of functions on remote machines
with corresponding inputs of type a and returns the processes
outputs, each of type b. The i-th process is supplied with the
i-th input generating the i-th output.
The number of processes (= length of output list) is determined by
the length of the shorter input list (thus one list may be infinite).

Instantiates a process defined by the given function on a remote machine, sends the input
of type a and returns the process output of type b in the parallel action monad, thus it can be combined to a larger parallel action.

Overloaded Communication

Communication of process inputs and outputs is done implicitly by the Eden runtime system.
The sent data has to be transmissible i.e. it has to be an instance of type class Trans. All
data will be evaluated to normal form before it is sent in one message. Communication is
overloaded for lists which are sent as streams element by element, and for tuples which are
sent using concurrent channel connections for each tuple element. Note that lists in
tuples are streamed concurrently, but a list of tuples
is streamed element-wise, with each tuple elements evaluated as a whole.
The inner list of nested lists will also be sent in one packet.

Trans class: overloads communication for streams and tuples.
You need to declare normal-form evaluation in an instance declaration of NFData.
Use the default implementation for write and createComm for instances of Trans.

Explicit placement

Remote Data

A remote data handle RD a represents data of type a which may be located on a remote machine. Such a handle is very small and can be passed via intermediate machines with only little communication overhead. You can create a remote data using the function
release and access a remote value using the function fetch.

This establishes a direct connection to the process which released the data in the first place. The result is in the parallel action monad and can be combined to a larger parallel action.
Notice that you have to fetch a remote value exactly once!

Transforms a list of remote data into a corresponding local data list.
map fetch would wait for each list element until fetching the next one.
Function fetchAll blocks only on partial defined list structure, not on content.

Parameter function that takes a channel name and a substitute for the lazily received value.

-> b

Forwarded result

A channel can be created with the function new (this is an unsafe side
effect!). It takes a function whose
first parameter is the channel name ChanName a and whose second parameter
is the value of type a that will be received lazily in the future. The
ChanName and the value of type a can be used in the body of the parameter
function to create the output of type b. The output of the parameter
function will be forwarded to the output of new .

You can connect to a reply channel with function parfill (this is an
unsafe side effect!). The first parameter is the name of the channel, the
second parameter is the value to be send. The third parameter will be the
functions result after the
concurrent sending operation is initiated. The sending operation will be
triggered as soon as the result of type b is demanded. Take care not to
make the result of parfill depend on the sent value, as this
will create a deadlock.

Nondeterminism

Non-deterministically merges a list of lists (usually input streams)
into a single list. The order of the output list is determined by the
availability of the inner lists constructors. (Function merge is defined
using Concurrent Haskell's function nmergeIO)

Reexported functions from Control.Parallel

Semantically identical to seq, but with a subtle operational
difference: seq is strict in both its arguments, so the compiler
may, for example, rearrange a `seq` b into b `seq` a `seq` b.
This is normally no problem when using seq to express strictness,
but it can be a problem when annotating code for parallelism,
because we need more control over the order of evaluation; we may
want to evaluate a before b, because we know that b has
already been sparked in parallel with par.

This is why we have pseq. In contrast to seq, pseq is only
strict in its first argument (as far as the compiler is concerned),
which restricts the transformations that the compiler can do, and
ensures that the user can retain control of the evaluation order.