Table of Contents

Enum TrialExecutorKind

Namespace
OptunaSharp
Assembly
OptunaSharp.dll

Which threads run the trials of Study.Optimize(nJobs: …) when nJobs is not 1. With nJobs: 1 every trial runs on the calling thread, whatever is chosen here.

public enum TrialExecutorKind

Fields

DedicatedThreads = 0

OptunaSharp's own dedicated background threads, never .NET thread-pool threads: created on demand, reused by later trials and later Optimize calls, and retired after ThreadIdleTimeout without work. The default, and the safe choice for any nJobs: nJobs trials really run at once, and the pool stays free for the host and for the storage clients that complete their calls on it.

ThreadPool = 1

The .NET thread pool, shared with the rest of the process.

Footgun. A trial blocks its thread for the whole trial (the storage's lock, network I/O, the objective). Once nJobs reaches the pool's minimum worker count (ThreadPool.GetMinThreads, the processor count by default), the pool adds threads only about once a second, so fewer than nJobs trials run at once. StackExchange.Redis and gRPC calls, which complete on the pool, then stall or time out, and the host's own work waits behind queued trials. Measured on 32 cores: Redis journals timed out from about 40 workers, a gRPC study took 54.5 s instead of 0.6 s at 96, and at most 34 trials ran at once (THREADING.md §3.6, §7.2). OptunaSharp does not guard against this.

If you hit thread-pool starvation, use DedicatedThreads, which reuses OptunaSharp's own threads, or raise the pool's minimum with ThreadPool.SetMinThreads to at least nJobs plus what the rest of the process needs.

Remarks

Optuna has no counterpart: Python always runs n_jobs on a ThreadPoolExecutor of its own threads, which is what DedicatedThreads ports. nJobs keeps Python's meaning on both kinds.