Skip to contents

Fitting a hestia model is the expensive part of most analyses. hestia fits through flexstanr, which owns the parallelism: how cores are detected, how they are split between chains and threads, and how that behaves under an HPC scheduler are all flexstanr behavior and are documented once, there:

  • Parallel and threaded fitting – the core-allocation rules, capping with max_cores, and the SLURM recipes (single node, and one chain per array task).

This article covers only what is specific to hestia.

Why threading helps a hestia fit

A fit can use cores in two ways at once: across chains, which are independent and so scale near-linearly, and within a chain. The within-chain half is the model-specific part. hestia’s likelihood sums over households, which are conditionally independent given the parameters, so that sum splits across threads with Stan’s reduce_sum. Both hmm and hmm_cov are compiled for threading, so a hestia fit can always use within-chain threads when there are spare cores to give them.

flexstanr fills chain-parallelism first and gives any leftover cores to threads, so threading only switches on when you have more cores than chains.

Turning it on

Threading is off unless you ask for it, and you ask for it through the same stan_options() you already pass to run_model():

# detect the cores this process is allowed to use and split them automatically
fit <- run_model(
  inf_model  = inf_process,
  obs_model  = obs_process,
  data       = sir,
  init_probs = c(1 - 2 * 1e-10, 1e-10, 1e-10),
  stan_opts  = stan_options(chains = 4, iter = 1000, threading = TRUE)
)

# cap the pool, for example to keep some cores free
fit <- run_model(
  ...,
  stan_opts = stan_options(chains = 4, threading = TRUE, max_cores = 6)
)

# single-threaded (the default): manage backend parallelism yourself
fit <- run_model(..., stan_opts = stan_options(threading = FALSE))

The same stan_opts works on a laptop and inside a scheduled job: flexstanr sizes the fit from the allocation the process actually has, not from the machine’s total core count. See the flexstanr article for the allocation rules and job-script templates, substituting run_model() for the fit call shown there.