Table of Contents

Enum SamplerConcurrency

Namespace
OptunaSharp
Assembly
OptunaSharp.dll

How the workers of one Study.Optimize(nJobs: …) call reach the study's sampler. With nJobs: 1, and for every Ask/Tell outside Optimize, the study's own sampler serves every trial, whatever is chosen here.

public enum SamplerConcurrency

Fields

Shared = 0

Every worker samples through the study's one sampler instance, one call at a time (the sampler's monitor, THREADING.md §6.3). The default, and Optuna's model: a seeded sampler draws from one generator, and samplers that propose from shared state (QMC's sequence, the evolution strategies' generations) never hand two trials the same point because of the parallelism. The cost: sampling is serial, so a sampler whose proposals are slow caps the throughput at one proposal per sampling time, whatever nJobs is (measured 2026-11-08: GPSampler ran 120 trials of a 20 ms objective in 18.7 s at nJobs: 8 against 12.1 s at nJobs: 1).

PerWorker = 1

Each worker samples with an instance of its own: made from the study's sampler (same configuration), reseeded from fresh OS entropy before each of its trials as Optuna reseeds a worker, and reused by that worker for later trials of the call. The instances share only the storage, so they sample in parallel, exactly like separate processes on one storage.

When it pays. Only when sampling, not the objective, limits the run. Measured 2026-11-08 at nJobs: 8 on 32 cores: a multivariate TPE over 10 parameters (600 trials, 5 ms objective) took 1.20 s against 1.95 s shared, and a 40-dimensional CMA-ES (2,000 trials, no sleep) 1.46 s against 3.68 s; a univariate TPE over 3 parameters with a 20 ms objective gained nothing (1.54 s against 1.56 s).

Only samplers that produce no duplicate samples this way take part: RandomSampler, TPESampler (multivariate or not), CmaEsSampler, VkdCmaSampler, GridSampler, and PartialFixedSampler over one of them. Every other sampler keeps Shared access, one call at a time, because separate instances propose the same point: measured with eight instances on one study (three rounds of 64 trials, fewer for the slow model-based samplers), QMC repeated 4–20 points a round, the NES samplers 21–29, JANUS and JANUS-DE 49–54, PSO, TuRBO, REMBO, SAASBO and BruteForce 2–32, and GPSampler one point in eleven rounds of 24 trials (none shared): instances that see the same history optimize the same acquisition function. A sampler written outside OptunaSharp also keeps Shared access.

Footguns. Functions passed to a taking-part sampler (TPE's gamma, weights and constraintsFunc, for example) now run on several workers at once, so they must be thread-safe. Trials of one call no longer draw from one generator, so a seeded sampler's parallel run is no more reproducible than before (it never was, THREADING.md §3.2). The study's own sampler instance is not used by the workers of such a call, so state it keeps in memory (TPE's caches, CMA-ES's) is not updated by them.

Remarks

Optuna has no counterpart: its n_jobs threads share the study's one sampler object, which is what Shared ports. Several samplers sampling in parallel exist in Optuna only as several processes on one storage, and that is what PerWorker reproduces inside one process.