Piecemeal R6 ClassThis class exports methods for configuring a simulation, running it, debugging failed configurations, and resuming the simulation. See the vignette vignette("piecemeal") for long worked example.
new()Create a new Piecemeal instance.
Piecemeal$new(outdir)outdirthe directory to hold the partial simulation results.
cluster()Cluster settings for the piecemeal run.
Piecemeal$cluster(...)...either arguments to makeCluster() or a single argument containing either an existing cluster or NULL to disable clustering.
export_vars()Specify variables to be copied from the manager node to the worker nodes' global environment. (See parallel::clusterExport().)
Piecemeal$export_vars(varlist, envir = parent.frame(), .add = TRUE)varlista character vector with variable names.
envirthe environment on the manager node from which to take the variables; defaults to the current environment.
.addwhether the new variables should be added to the current list (if TRUE, the default) or replace it (if FALSE).
setup()Specify code to be run on each worker node at the start of the simulation; if running locally, it will be evaluated in the global environment.
Piecemeal$setup(
expr = {
}
)expran expression; if passed, replaces the previous expression; if empty, resets it to nothing.
worker()Specify the function to be run for each treatment configuration; it will be run in the global environment.
Piecemeal$worker(fun)funa function whose arguments are specified by $treatments() and $factorial(); if it has .seed as a named argument, the seed will be passed as well.
treatments()Specify a list of treatment configurations to be run.
Piecemeal$treatments(l, .add = TRUE)la list, typically of lists of arguments to be passed to the function specified by worker; it is recommended that these be as compact as possible, since they are serialized and sent to the worker node for every combination of treatment configuration and random seed.
.addwhether the new treatment configurations should be added to the current list (if TRUE, the default) or replace it (if FALSE.
factorial()Specify a list of treatment configurations to be run in a factorial design.
Piecemeal$factorial(..., .filter = function(...) TRUE, .add = TRUE)...vectors or lists whose Cartesian product will added to the treatment list; it is recommended that these be as compact as possible, since they are serialized and sent to the worker node for every combination of treatment configuration and random seed.
.filtera function that takes the same arguments as worker and returns FALSE if the treatment configuration should be skipped; defaults to accepting all configurations.
.addwhether the new treatment configurations should be added to the current list (if TRUE, the default) or replace it (if FALSE.
nrep()Specify a number of replications for each treatment configuration (starts out at 1).
Piecemeal$nrep(nrep)nrepa positive integer giving the number of replications; the seeds will be set to 1:nrep.
seeds()Specify the seeds to be used for each replication of each treatment configuration.
Piecemeal$seeds(seeds)seedsan integer vector of seeds; its length will be used to infer the number of replications.
run()Run the simulation.
Piecemeal$run(shuffle = TRUE)shuffleShould the treatment configurations be run in a random order (TRUE, the default) or in the order in which they were added (FALSE)?
Invisibly, a character vector with an element for each seed and treatment configuration combination attempted, indicating its file name and status, including errors.
todo()List the configurations still to be run.
Piecemeal$todo()A list of lists with arguments to the worker functions and worker-specific configuration settings; also an attribute "done" giving the number of configurations skipped because they are already done.
result_list()Scan through the results files and collate them into a list.
Piecemeal$result_list(n = Inf, trt_tf = identity, out_tf = identity)nmaximum number of files to load; if less than the number of results, a systematic sample is taken.
trt_tf, out_tffunctions that take the treatment configuration list and the output (if not an error) respectively, and transform them; this is helpful when, for example, the output is big and so loading all the files will run out of memory.
A list of lists containing the contents of the result files.
treatmentarguments passed to the worker
seedthe seed set just before calling the worker
outputvalue returned by the worker, or a try-error returned by try()
OKwhether the worker succeeded or produced an error
configmiscellaneous configuration settings such as the file name
result_df()Scan through the results files and collate them into a data frame.
Piecemeal$result_df(trt_tf = identity, out_tf = identity, rds = FALSE, ...)trt_tf, out_tffunctions that take the treatment configuration list and the output respectively, and return named lists that become data frame columns; a special value I instead creates columns treatment and/or output with the respective lists copied as is.
rdswhether to include an .rds column described below.
...additional arguments, passed to Piecemeal$result_list().
A data frame with columns corresponding to the values returned by trt_tf and out_tf, with the following additional columns:
.seedthe random seed used.
.rdsthe path to the RDS file (if requested).
Runs that erred are filtered out.
reset()Clear the simulation results so far.
Piecemeal$reset(confirm = interactive())confirmwhether the user should be prompted to confirm deletion.
clean()Delete the result files for which the worker function produced an error and/or which were somehow corrupted, or based on some other predicate.
Piecemeal$clean(which = function(res) !res$OK)whicha function of a result list (see Piecemeal$result_list()) returning TRUE if the result file is to be deleted and FALSE otherwise.
erred()List the configurations for which the worker function failed.
Piecemeal$erred()
options()Set miscellaneous options.
Piecemeal$options(split = c(1L, 1L), error = c("auto", "save", "skip", "stop"))splita two-element vector indicating whether the output files should be split up into subdirectories and how deeply, the first for splitting configurations and the second for splitting seeds; this can improve performance on some file systems.
errorhow to handle worker errors:
"save"save the seed, the configuration, and the status, preventing future runs until the file is removed using Piecemeal$clean().
"skip"return the error message as a part of run()'s return value, but do not save the RDS file; the next run() will attempt to run the worker for that configuration and seed again.
"stop"allow the error to propagate; can be used in conjunction with Piecemeal$cluster(NULL) and (global) options(error = recover) to debug the worker.
"auto"(default) as "save", but if any of the methods that change how each configuration is run (i.e., $worker(), $setup(), and $export_vars()) is called, $clean() will be called automatically before the next $run().
print()Print the current simulation settings, including whether there is enough information to run it.
Piecemeal$print(...)...additional arguments, currently unused.
status()Summarise the current status of the simulation, including the number of runs succeeded, the number of runs still to be done, the number of runs currently running, the errors encountered, and, if started, the estimated time to completion at the current rate.
Piecemeal$status(...)...additional arguments, currently passed to Piecemeal$eta().
eta()Estimate the rate at which runs are being completed and how much more time is needed.
Piecemeal$eta(window = 3600)windowinitial time window to use, either a difftime object or the number in seconds; defaults to 1 hour.
The window used is actually between the last completed run and the earliest run in the window before that. This allows to take an interrupted simulation and estimate how much more time (at the most recent rate) is needed.
A list with elements window, recent, cost, left, rate, and eta, containing, respectively, the time window, the number of runs completed in this time, the average time per completion, the estimated time left (all in seconds), the corresponding rate (in Hertz), and the expected time of completion.
clone()The objects of this class are cloneable with this method.
Piecemeal$clone(deep = FALSE)deepWhether to make a deep clone.
A chain of R6 method calls is used to specify the setup and the worker functions, the treatment configurations to be passed to the worker, and parallelism and other simulation settings. Then, when $run() is called, the cluster is started, worker nodes are initialised, and every combination of random seed and treatment configuration is passed to clusterApplyLB() (if parallel processing is enabled).
On the worker nodes, the worker function is not called directly; rather, care is taken to make sure that the specified configuration and seed is not already being worked on. This makes it safe to, e.g., queue multiple jobs for the same simulation. If the configuration is available, set.seed() is called with the seed and then the worker function is run.
Errors in the worker function are caught and error messages saved and returned.
# Initialise, with the output directory.
sim <- piecemeal::init(file.path(tempdir(), "piecemeal_demo"))
# Clear the previous simulation, if present.
sim$reset()
# Set up a simulation:
sim$
# for every combination of x = 1, 2 and y = 1, 3, 9, 27,
factorial(x = 2^(0:1), y = 3^(0:3))$
# each replicated 3 times,
nrep(3)$
# first load library 'rlang',
setup({library(rlang)})$
# then for each x, y, and seed, evaluate
worker(function(x, y) {
p <- x*y
u <- runif(1)
dbl(p = p, u = u)
})$
# on a cluster with two nodes.
cluster(2)
# Summarise
sim
# Go!
sim$run()
# Get a table with the results.
sim$result_df()
# For a more involved version of this example, see vignette("piecemeal").
Run the code above in your browser using DataLab