run(3) | run(3) |
node - adapt function to execute on remote node
#include <cfl/run/node.hpp>
auto f = [] (int u) { return u + 1; };
auto g = node (1, f); // 1_node (f);
auto r = g (0);
node
adapts a function for remote execution. There is a corresponding
user-defined literal _node
for convenience. When an adapted function is
invoked, it (immediately) returns a future to a remote future.
Function and arguments are put in a send queue and sent to the remote node, preserving call order. When received at the remote node, a remote future is sent back as receipt to caller, and function invocation is (autmoatically) submitted to a task queue, preserving the same order. Once evaluated, a remote value is sent back as reply to the original caller. However, task completion order is indeterminate, as well as reply order.
The different stages of evaluation can be forced using a set of modifiers:
send
, receipt
, wait
, get
, fetch
, fetch_wait
or fetch_get
, with
slightly different meaning depending on whether they operate on the function g
or the result r
.
drop (g)
:
Modify g
to not send any response at all.
send (r)
:
Wait until message in send queue is sent.
send (g)
:
When invoked, do not return until message in send queue is sent.
receipt (r)
:
Wait until the remote future is received.
receipt (g)
:
When invoked, do not return until the remote future is received.
wait (r)
:
Wait until the remote value is received.
wait (g)
:
Modify g
to (remotely) return a remote value instead of a remote future,
i.e. skip the receipt step. When invoked (locally), do not return until remote
value is received.
get (r)
:
Wait until the remote value is received, and return a remote reference.
get (g)
:
As wait (g)
above, and return the remote reference.
fetch (r)
:
Request remote value to be sent here.
fetch (g)
:
Modify g
to (remotely) return a value instead of a remote future, i.e.
skip the receipt and wait steps.
fetch_wait (r)
:
Wait until the local value is received. Implies fetch (r)
.
fetch_wait (g)
:
Modify g
to (remotely) return a remote value instead of a remote future,
i.e. skip the receipt step. When invoked (locally), do not return until local
value is received. Implies fetch (g)
.
fetch_get (r)
:
As fetch_wait (r)
above, and return a reference to the local value.
fetch_get (g)
:
As fetch_wait (g)
above, and return the local value.
As an example, to execute remotely and get an asynchronous local result:
auto r = fetch (g) (0);
Asynchronous remote values can be used as arguments to container functions. The return type is changed correspondingly to a future instead.
auto h = cfn ([] (int u) { return u + 2; });
auto s = h (r);
Here, the value in the remote future is fetched and passed to h
asynchronously.
Nested remote calls are currently limited to remote value arguments, so a
wait
call is implied for such arguments.
A function. When invoked, it executes on a remote node and locally immediately returns a future to a remote future.
Both node
and its resulting function are container functions.
In the case of over-subscription (i.e. when the program runs with more
processes than there are available nodes), another “node” may actually be a
processes residing on the same machine as the caller. Because of this, the name
node
is slightly misleading. MPI uses the term rank
instead, but in CFL this
conflicts with the rank of arrays. Between the two, CFL chose node
, as
over-subscription is not the first choice to parallelize work. Local
communication is done through a UNIX socket, so it is normally faster than over
the network, but data is still serialized and sent between the two processes. A
better alternative would be to defer work to local threads instead.