How do I set the `brms` arguments "threads" and "cores" correctly?

Suppose I want to run 4 chains, but my computer has 16 cores. I want to then make use of all 16 cores on my computer while running my brms model.

The threads argument represents the number of threads that will be used for each chain, but it’s not clear to me how this interacts with the cores variable.

If I set chains = 4, cores = 16, threads = threading(4), I get an informative message from brms that says

“Running MCMC with 4 chains, at most 16 in parallel, with 4 thread(s) per chain…”.

It’s not quite clear to me what this means. It’s clearly running all of the chains in parallel, but is this also the correct way to specify the threads argument so that I am using (potentially) all 16 available cores at once? I think the order of the wording is what confuses me here. If the message said “4 chains and 4 thread(s) per chain, at most 16 threads in parallel” that would confirm that the model is doing what I want. But the current wording of the message potentially implies to me that 4 chains are being run in parallel on 4 chains, and the other 12 cores aren’t being used.

So is the way I set up these arguments correct, or do I need to do something else?

I know that it’s also possible to set up the parallelization options with future, but from the examples I don’t really understand how to set up the future plan to use multiple threads per chain.

(Sideote: I know that in general running 16 chains would likely be faster in this example, I just want an easy to understand example. And I know that it’s better to leave at least one core open.)

My understanding is that the argument cores refers to the maximum number of MCMC chains to run in parallel, and the argument threads refers to the number of threads to use within an MCMC chain. So the actual number of CPU cores used will be cores * threads.

In your case, you should set cores = 4 and threads = threading(4).

You can verify this yourself by looking at parts of the brms source code to see how the brms arguments are passed to the cmdstanr backend. Here’s a relevant snippet of code:

    c(args) <- nlist(
      iter_sampling = iter - warmup,
      iter_warmup = warmup,
      chains, thin,
      parallel_chains = cores,
      show_messages = silent < 2,
      show_exceptions = silent == 0,
      fixed_param = algorithm == "fixed_param"
    )
    if (use_threading) {
      args$threads_per_chain <- threads$threads
    }

So the brms arguments chains, cores, and threads correspond to chains, parallel_chains, and threads_per_chain respectively in the sample method of cmdstanr. You can then check the cmdstanr documentation to verify my explanation above.

1 Like