Set daemons, or persistent background processes, to receive mirai()
requests. Specify n to create daemons on the local machine. Specify url
to receive connections from remote daemons (for distributed computing across
the network). Specify remote to optionally launch remote daemons via a
remote configuration. Dispatcher (enabled by default) ensures optimal
scheduling.
Usage
daemons(
n,
url = NULL,
remote = NULL,
dispatcher = TRUE,
...,
sync = FALSE,
seed = NULL,
serial = NULL,
tls = NULL,
pass = NULL,
.compute = NULL
)Arguments
- n
(integer) number of daemons to launch.
- url
(character) URL at which to listen for daemon connections, e.g. 'tcp://hostname:5555'. Use scheme 'tls+tcp://' for secure TLS connections (see Distributed Computing section).
host_url()may be used to construct a valid URL.- remote
(configuration) for launching remote daemons, generated by
ssh_config(),cluster_config(), orremote_config().- dispatcher
(logical) whether to use dispatcher for optimal FIFO scheduling. See Dispatcher section below.
- ...
(daemon arguments) passed to
daemon()when launching daemons. Includesasyncdial,autoexit,cleanup,output,maxtasks,idletime,walltime, andtlscert.- sync
(logical) whether to evaluate mirai synchronously in the current process for testing and debugging. When
TRUE, other arguments exceptseedand.computeare disregarded.- seed
(integer) for reproducible random number generation.
NULL(default) initializes L'Ecuyer-CMRG RNG streams per daemon (statistically sound, non-reproducible). An integer value instead initializes a stream per mirai (experimental), allowing reproducible results independent of which daemon evaluates it.- serial
(configuration) for custom serialization of reference objects (e.g. Arrow Tables, torch tensors), created by
serial_config(). Requires dispatcher.NULLapplies any configurations fromregister_serial().- tls
(character) for secure TLS connections. Either a file path to PEM-encoded TLS certificate (possibly followed by other certificates in a validation chain) and private key, or a length-2 vector of (certificate, private key).
NULLauto-generates single-use credentials.- pass
(function) returning the password for an encrypted
tlsprivate key. Use a function rather than a direct value for security.- .compute
(character) name of the compute profile. Each profile has its own independent set of daemons.
NULL(default) uses the 'default' profile.
Details
Use daemons(0) to reset daemon connections:
All connected daemons and/or dispatchers exit automatically.
Any as yet unresolved 'mirai' will return an 'errorValue' 19 (Connection reset).
mirai()reverts to the default behaviour of creating a new background process for each request.
If the host session ends, all connected dispatcher and daemon processes automatically exit as soon as their connections are dropped.
Calling daemons() implicitly resets any existing daemons for the compute
profile with daemons(0). Instead, launch_local() or launch_remote() may
be used to add daemons at any time without resetting daemons.
Local Daemons
Setting daemons, or persistent background processes, is typically more efficient as it removes the need for, and overhead of, creating new processes for each mirai evaluation. It also provides control over the total number of processes at any one time.
Supply the argument n to set the number of daemons. New background
daemon() processes are automatically launched on the local machine
connecting back to the host process, either directly or via dispatcher.
Dispatcher
By default dispatcher = TRUE launches a background process running
dispatcher(). Dispatcher connects to daemons on behalf of the host, queues
tasks, and ensures optimal FIFO scheduling. Dispatcher also enables (i) mirai
cancellation using stop_mirai() or when using a .timeout argument to
mirai(), and (ii) the use of custom serialization configurations.
Specifying dispatcher = FALSE, daemons connect directly to the host and
tasks are distributed in a round-robin fashion, with tasks queued at each
daemon. Optimal scheduling is not guaranteed as, depending on the duration of
tasks, they can be queued at one daemon while others remain idle. However,
this solution is the most resource-light, and suited to similar-length tasks,
or where concurrent tasks typically do not exceed available daemons.
Distributed Computing
Specify url as a character string to allow tasks to be distributed across
the network (n is only required in this case if also providing a launch
configuration to remote).
The host / dispatcher listens at this URL, utilising a single port, and
daemon() processes dial in to this URL. Host / dispatcher automatically
adjusts to the number of daemons actually connected, allowing dynamic
upscaling / downscaling.
The URL should have a 'tcp://' scheme, such as 'tcp://10.75.32.70:5555'.
Switching the URL scheme to 'tls+tcp://' automatically upgrades the
connection to use TLS. The auxiliary function host_url() may be used to
construct a valid host URL based on the computer's IP address.
IPv6 addresses are also supported and must be enclosed in square brackets
[] to avoid confusion with the final colon separating the port. For
example, port 5555 on the IPv6 loopback address ::1 would be specified as
'tcp://[::1]:5555'.
Specifying the wildcard value zero for the port number e.g. 'tcp://[::1]:0'
will automatically assign a free ephemeral port. Use status() to inspect
the actual assigned port at any time.
Specify remote with a call to ssh_config(), cluster_config() or
remote_config() to launch (programatically deploy) daemons on remote
machines, from where they dial back to url. If not launching daemons,
launch_remote() may be used to generate the shell commands for manual
deployment.
Compute Profiles
If NULL, the "default" compute profile is used. Providing a character
value for .compute creates a new compute profile with the name specified.
Each compute profile retains its own daemons settings, and may be operated
independently of each other. Some usage examples follow:
local / remote daemons may be set with a host URL and specifying
.compute as "remote", which creates a new compute profile. Subsequent
mirai() calls may then be sent for local computation by not specifying the
.compute argument, or for remote computation to connected daemons by
specifying the .compute argument as "remote".
cpu / gpu some tasks may require access to different types of daemon,
such as those with GPUs. In this case, daemons() may be called to set up
host URLs for CPU-only daemons and for those with GPUs, specifying the
.compute argument as "cpu" and "gpu" respectively. By supplying the
.compute argument to subsequent mirai() calls, tasks may be sent to
either cpu or gpu daemons as appropriate.
Note: further actions such as resetting daemons via daemons(0) should
be carried out with the desired .compute argument specified.
See also
with_daemons() and local_daemons() for managing the compute
profile used locally.
Examples
if (FALSE) { # interactive()
# Create 2 local daemons (using dispatcher)
daemons(2)
info()
# Reset to zero
daemons(0)
# Create 2 local daemons (not using dispatcher)
daemons(2, dispatcher = FALSE)
info()
# Reset to zero
daemons(0)
# Set up dispatcher accepting TLS over TCP connections
daemons(url = host_url(tls = TRUE))
info()
# Reset to zero
daemons(0)
# Set host URL for remote daemons to dial into
daemons(url = host_url(), dispatcher = FALSE)
info()
# Reset to zero
daemons(0)
# Use with() to evaluate with daemons for the duration of the expression
with(
daemons(2),
{
m1 <- mirai(Sys.getpid())
m2 <- mirai(Sys.getpid())
cat(m1[], m2[], "\n")
}
)
if (FALSE) { # \dontrun{
# Launch daemons on remotes 'nodeone' and 'nodetwo' using SSH
# connecting back directly to the host URL over a TLS connection:
daemons(
url = host_url(tls = TRUE),
remote = ssh_config(c('ssh://nodeone', 'ssh://nodetwo'))
)
# Launch 4 daemons on the remote machine 10.75.32.90 using SSH tunnelling:
daemons(
n = 4,
url = local_url(tcp = TRUE),
remote = ssh_config('ssh://10.75.32.90', tunnel = TRUE)
)
} # }
}
# Synchronous mode
# mirai are run in the current process - useful for testing and debugging
daemons(sync = TRUE)
m <- mirai(Sys.getpid())
daemons(0)
m[]
#> [1] 6996
# Synchronous mode restricted to a specific compute profile
daemons(sync = TRUE, .compute = "sync")
with_daemons("sync", {
m <- mirai(Sys.getpid())
})
daemons(0, .compute = "sync")
m[]
#> [1] 6996
