One row per run, with compile time and sampling time kept apart, ESS
per chain-second for bulk and tail, and the cost of one gradient
evaluation. Runs are interleaved — A, B, A, B — because running
every A before every B would confound the comparison with drift in
machine load, and the first run of each implementation is discarded:
it carries the fresh compile and a cold machine. The discarded run is
still returned, marked warmup_run, so that nothing is dropped
silently.
Usage
benchmark(
implementations,
data,
...,
runs = 5L,
warmup_runs = 1L,
compile = TRUE,
on_error = c("record", "stop"),
.metrics = NULL,
.compiler = NULL
)Arguments
- implementations
A named list, one element per implementation. Each is either a function
(data, ...) -> fitor a list with afitfunction and, optionally, acompilefunction(data, ...) -> Stan codewhose compile is timed once.- data
A data frame used for every pair, or a list of data frames, one per pair. A list is not recycled: it must hold
runs + warmup_runssets, because a reused data set would make the paired ratios dependent.- ...
Passed to every implementation's fitter (
chains,iter,cores,seed,backend, ...). Pass the same arguments to all of them;summary()warns when the recorded settings differ. With aseed, each fit is also called underwithr::with_seed(seed), as infit_cached(), so that the initial values bmm draws from R's random number generator are the same in every run. With one data frame fordataand aseed, every run of an implementation is therefore the same fit, with the same draws and the same ESS; only the wall time varies, so the intervalsummary()gives for the ESS-per-second ratio measures timing noise of the machine, not variation between fits. To measure efficiency across fits, pass a list of data sets, one per pair.- runs
Recorded pairs per implementation.
- warmup_runs
Leading runs per implementation that are recorded and then excluded from
summary().- compile
Measure a forced compile once per implementation, for those that supply a
compilehook.- on_error
"record"keeps a row whose measurements areNA, puts the message inerrorand goes on;"stop"aborts.- .metrics
The measuring function,
benchmark_metrics()by default. Tests inject a stand-in so that no model is fitted.- .compiler
Passed to
benchmark_compile().
Value
A tibble of class bmmtools_benchmark, one row per run:
identity —
implementation,pair(0 for a warmup pair),run,warmup_run,data_id,data_rows;settings as run —
backend,chains,iter,warmup,thin,fit_cores,fit_threads,seed;time in seconds —
wall_seconds(the fitting call),compile_secondswithcompile_source,warmup_chain_seconds,sampling_chain_seconds,total_chain_seconds(each summed over chains),max_chain_secondsandoverhead_seconds(wall_seconds - max_chain_seconds, which contains a per-fit compile under a backend that recompiles, and R-side overhead under cmdstanr with a cached executable);work —
leapfrog_sampling,leapfrog_warmup(NAunless warmup draws were saved),us_per_gradient(the median over chains of chain sampling time over chain leapfrog steps), withus_per_gradient_min,us_per_gradient_maxandus_per_gradient_warmup;efficiency —
ess_bulk_min,ess_tail_minand the four ratesess_{bulk,tail}_per_chain_sec_{sampling,total}, per chain-second, over post-warmup or over warmup plus sampling;what the speed must be read with —
max_rhat,n_divergent,n_max_treedepth,n_variables,converged,error;every
run_info()column, per run.
The per-chain table of every run is in the attribute chains, the
compile table in compile, and the call and its arguments in
settings.
Details
No fit is written. The module never calls fit_cached(), so a
benchmark fit can never be served to a recovery grid, and no cache key
changes because of it.
Examples
if (FALSE) { # \dontrun{
bench <- benchmark(
implementations = list(
current = function(data, ...) brms::brm(current_formula, data, ...),
rebuilt = function(data, ...) {
bmm::bmm(
bmm::bmf(kappa ~ 1, thetat ~ 1), data,
bmm::mixture2p(resp_error = "y"), ...
)
}
),
data = data_sets, runs = 5,
backend = "cmdstanr", chains = 4, iter = 2000, cores = 4
)
summary(bench)$ratios
} # }
