Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ionworks.com/llms.txt

Use this file to discover all available pages before exploring further.

Ionworks uses Ray to distribute optimization work across available CPUs, with Anyscale providing autoscaling infrastructure. This page explains how resources are allocated across multistart runs and when distributed evaluation is used to accelerate population-based optimizers.

Two Levels of Parallelism

Ionworks applies parallelism at two levels during optimization:

Batch-level: Multistart Runs

When you configure multiple multistarts, each run is dispatched as a separate Ray task. Each task reserves 1 CPU to act as a coordinator, and Ray’s scheduler manages concurrency — if more multistarts are requested than available resources, excess tasks are queued and executed as resources free up.

Optimizer-level: Distributed Evaluation

Population-based optimizers evaluate a population of candidate solutions every iteration. When workers are available, these evaluations are distributed across Ray worker processes using an ActorPoolEvaluator with SPREAD placement groups for cross-node distribution. The following optimizers are population-based and support distributed evaluation:
OptimizerDescription
Differential Evolution (default)Adaptive mutation and crossover with global search
CMA-ESCovariance Matrix Adaptation Evolution Strategy
PSOParticle Swarm Optimization
XNESExponential Natural Evolution Strategy
Non-population-based optimizers (e.g. Nelder-Mead) cannot distribute their evaluations and always run sequentially on a single coordinator.

Async evaluation mode

When async mode is enabled, population-based optimizers submit candidate evaluations and begin processing results as soon as any worker finishes, rather than waiting for the entire population batch to complete. This reduces idle time when individual evaluations vary in duration — fast evaluations are fed back to the optimizer immediately while slower ones continue in the background. Async mode is enabled automatically when distributed evaluation is available. It applies to all population-based optimizers (Differential Evolution, CMA-ES, PSO, XNES, SNES). Non-population-based optimizers are unaffected.
Async evaluation does not change optimization results — it only affects throughput. The optimizer receives the same candidate-result pairs regardless of evaluation order.

Resource Allocation

Worker allocation depends on the cluster type and configuration: Uncapped Anyscale (default): Each multistart job receives a fixed number of workers (default: 4, configurable via ANYSCALE_WORKERS_PER_JOB). The Anyscale autoscaler provisions the required resources as placement groups are requested, scaling the cluster up and down based on demand. Each job gets its full worker allocation without competing for a fixed pool of CPUs. Capped Anyscale / Local clusters: Workers are dynamically partitioned based on available CPUs and the number of concurrent coordinators. The formula is (max_cpus - concurrent_coordinators) // concurrent_coordinators. On Anyscale, the cap is set via ANYSCALE_MAX_CLUSTER_CPUS. On local clusters, the current cluster CPU count is used. If the resulting worker count falls below the minimum threshold, distributed evaluation is skipped and the optimizer evaluates sequentially.
On uncapped Anyscale clusters, the worker count per job can be configured via the ANYSCALE_WORKERS_PER_JOB environment variable. On capped or local clusters, workers are determined automatically from available resources.

Scenarios

The following examples illustrate how resources are allocated in different configurations.

Scenario 1: Multiple Multistarts with a Population-based Optimizer (Uncapped Anyscale)

4 multistarts with CMA-ES Each multistart reserves 1 coordinator CPU and is assigned 4 workers for distributed evaluation. The autoscaler provisions a total of 20 CPUs (4 coordinators + 16 workers). Each run’s population evaluations are distributed across its workers via ActorPoolEvaluator.

Scenario 2: Single Multistart with a Population-based Optimizer (Uncapped Anyscale)

1 multistart with PSO A single coordinator is assigned 4 workers. The autoscaler provisions 5 CPUs total. All workers are dedicated to distributing the population evaluations for that single run.

Scenario 3: Many Multistarts (Uncapped Anyscale)

32 multistarts with CMA-ES Each multistart gets a coordinator and 4 workers. The autoscaler scales the cluster to meet demand. Ray’s scheduler manages concurrency — if the cluster hasn’t fully scaled yet, excess tasks are queued and start as resources become available.

Scenario 4: Multiple Multistarts on a Local Cluster

4 multistarts with CMA-ES on a 20-CPU local cluster Workers are dynamically partitioned: (20 - 4) // 4 = 4 workers per job. Each run gets 4 workers and 1 coordinator, using all 20 CPUs. On a smaller 8-CPU cluster with the same 4 multistarts, each job would get (8 - 4) // 4 = 1 worker — below the minimum threshold, so distributed evaluation is skipped.

Scenario 5: Single Multistart with a Non-population-based Optimizer

1 multistart with Nelder-Mead A single coordinator runs one optimization job. Because Nelder-Mead is not population-based, it cannot distribute evaluations to workers. The coordinator evaluates candidates sequentially.

Summary

ScenarioCoordinatorsWorkers/JobDistributed EvalAsync ModeBehavior
N multistarts, population-based (Anyscale)N4 (default)YesYesAutoscaler provisions N × 5 CPUs; results processed as they arrive
N multistarts, population-based (local/capped)NdynamicYesYesWorkers = (max_cpus - N) / N; results processed as they arrive
1 multistart, population-based14 (default) or dynamicYesYesWorkers evaluate population in parallel with async dispatch
N multistarts, non-population-basedN0NoNoSequential evaluation per job
1 multistart, non-population-based10NoNoSingle coordinator, sequential

Next Steps