forked from M-Labs/artiq
doc: remote execution
This commit is contained in:
parent
221d1bde0c
commit
eb68ab9ad0
@ -1,3 +1,38 @@
|
|||||||
|
"""
|
||||||
|
This module provides facilities for experiment to execute code remotely on
|
||||||
|
controllers.
|
||||||
|
|
||||||
|
The remotely executed code has direct access to the driver, so it can transfer
|
||||||
|
large amounts of data with it, and only exchange higher-level, processed data
|
||||||
|
with the experiment (and over the network).
|
||||||
|
|
||||||
|
Controllers with support for remote execution contain an additional target
|
||||||
|
that gives RPC access to instances of ``RemoteExecServer``. One such instance
|
||||||
|
is created per client (experiment) connection and manages one Python namespace
|
||||||
|
in which the experiment can execute arbitrary code by calling the methods of
|
||||||
|
``RemoteExecServer``.
|
||||||
|
|
||||||
|
The namespaces are initialized with the following global values:
|
||||||
|
|
||||||
|
* ``controller_driver`` - the driver instance of the controller.
|
||||||
|
* ``controller_initial_namespace`` - a controller-wide dictionary copied
|
||||||
|
when initializing a new namespace.
|
||||||
|
* all values from ``controller_initial_namespace``.
|
||||||
|
|
||||||
|
Access to a controller with support for remote execution is done through an
|
||||||
|
additional device database entry of this form: ::
|
||||||
|
|
||||||
|
"$REXEC_DEVICE_NAME": {
|
||||||
|
"type": "controller_aux_target",
|
||||||
|
"controller": "$CONTROLLER_DEVICE_NAME",
|
||||||
|
"target_name": "$TARGET_NAME_FOR_REXEC"
|
||||||
|
}
|
||||||
|
|
||||||
|
Specifying ``target_name`` is mandatory in all device database entries for all
|
||||||
|
controllers with remote execution support.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
@ -8,20 +43,37 @@ __all__ = ["RemoteExecServer", "simple_rexec_server_loop", "connect_global_rpc"]
|
|||||||
|
|
||||||
|
|
||||||
class RemoteExecServer:
|
class RemoteExecServer:
|
||||||
|
"""RPC target created at each connection by controllers with remote
|
||||||
|
execution support. Manages one Python namespace and provides RPCs
|
||||||
|
for code execution.
|
||||||
|
"""
|
||||||
def __init__(self, initial_namespace):
|
def __init__(self, initial_namespace):
|
||||||
self.namespace = dict(initial_namespace)
|
self.namespace = dict(initial_namespace)
|
||||||
# The module actually has to exist, otherwise it breaks e.g. Numba
|
# The module actually has to exist, otherwise it breaks e.g. Numba
|
||||||
self.namespace["__name__"] = "artiq.protocols.remote_exec"
|
self.namespace["__name__"] = "artiq.protocols.remote_exec"
|
||||||
|
|
||||||
def add_code(self, code):
|
def add_code(self, code):
|
||||||
|
"""Executes the specified code in the namespace.
|
||||||
|
|
||||||
|
:param code: a string containing valid Python code
|
||||||
|
"""
|
||||||
exec(code, self.namespace)
|
exec(code, self.namespace)
|
||||||
|
|
||||||
def call(self, function, *args, **kwargs):
|
def call(self, function, *args, **kwargs):
|
||||||
|
"""Calls a function in the namespace, passing it positional and
|
||||||
|
keyword arguments, and returns its value.
|
||||||
|
|
||||||
|
:param function: a string containing the name of the function to
|
||||||
|
execute.
|
||||||
|
"""
|
||||||
return self.namespace[function](*args, **kwargs)
|
return self.namespace[function](*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def simple_rexec_server_loop(target_name, target, host, port,
|
def simple_rexec_server_loop(target_name, target, host, port,
|
||||||
description=None):
|
description=None):
|
||||||
|
"""Runs a server with remote execution support, until an exception is
|
||||||
|
raised (e.g. the user hits Ctrl-C) or termination is requested by a client.
|
||||||
|
"""
|
||||||
initial_namespace = {"controller_driver": target}
|
initial_namespace = {"controller_driver": target}
|
||||||
initial_namespace["controller_initial_namespace"] = initial_namespace
|
initial_namespace["controller_initial_namespace"] = initial_namespace
|
||||||
targets = {
|
targets = {
|
||||||
@ -33,6 +85,23 @@ def simple_rexec_server_loop(target_name, target, host, port,
|
|||||||
|
|
||||||
def connect_global_rpc(controller_rexec, host=None, port=3251,
|
def connect_global_rpc(controller_rexec, host=None, port=3251,
|
||||||
target="master_dataset_db", name="dataset_db"):
|
target="master_dataset_db", name="dataset_db"):
|
||||||
|
"""Creates a global RPC client in a controller that is used across
|
||||||
|
all remote execution connections. With the default parameters, it connects
|
||||||
|
to the dataset database (i.e. gives direct dataset access to experiment
|
||||||
|
code remotely executing in controllers).
|
||||||
|
|
||||||
|
If a global object with the same name already exists, the function does
|
||||||
|
nothing.
|
||||||
|
|
||||||
|
:param controller_rexec: the RPC client connected to the controller's
|
||||||
|
remote execution interface.
|
||||||
|
:param host: the host name to connect the RPC client to. Default is the
|
||||||
|
local end of the remote execution interface (typically, the ARTIQ
|
||||||
|
master).
|
||||||
|
:param port: TCP port to connect the RPC client to.
|
||||||
|
:param target: name of the RPC target.
|
||||||
|
:param name: name of the object to insert into the global namespace.
|
||||||
|
"""
|
||||||
if host is None:
|
if host is None:
|
||||||
host = controller_rexec.get_local_host()
|
host = controller_rexec.get_local_host()
|
||||||
code = """
|
code = """
|
||||||
|
@ -169,6 +169,11 @@ The program below exemplifies how to use logging: ::
|
|||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
Remote execution support
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
If you wish to support remote execution in your controller, you may do so by simply replacing ``simple_server_loop`` with :class:`artiq.protocols.remote_exec.simple_rexec_server_loop`.
|
||||||
|
|
||||||
General guidelines
|
General guidelines
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ and the ARTIQ kernels.
|
|||||||
|
|
||||||
$ mkdir build
|
$ mkdir build
|
||||||
$ cd build
|
$ cd build
|
||||||
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/llvm-or1k -DLLVM_TARGETS_TO_BUILD="OR1K;X86" -DCMAKE_BUILD_TYPE=Rel -DLLVM_ENABLE_ASSERTIONS=ON
|
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/llvm-or1k -DLLVM_TARGETS_TO_BUILD="OR1K;X86" -DLLVM_ENABLE_ASSERTIONS=ON
|
||||||
$ make -j4
|
$ make -j4
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
|
|
||||||
|
@ -34,3 +34,10 @@ Protocols reference
|
|||||||
|
|
||||||
.. automodule:: artiq.protocols.sync_struct
|
.. automodule:: artiq.protocols.sync_struct
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
:mod:`artiq.protocols.remote_exec` module
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: artiq.protocols.remote_exec
|
||||||
|
:members:
|
||||||
|
Loading…
Reference in New Issue
Block a user