Skip to main content

Module ensemble

Module ensemble 

Source
Expand description

Many independent samples, run in parallel, with an answer that does not depend on how many threads did the work.

The other axis of parallelism in this workspace. TreeNBody::with_threads splits one evaluation across cores; this splits many evaluations, which is the shape a Monte Carlo study has and the shape a parameter sweep has. A hundred thousand detector realisations, a thousand trajectories from perturbed initial conditions, a grid of designs each run to a steady state — all the same problem: independent work items and a reduction at the end.

§Why this can be parallel and still bit-for-bit

Two decisions that were already made, meeting.

Rng::for_index is stateless and addressed by index, so sample i draws the same numbers whether it ran first, last, or on another core. Nothing is consumed from a shared stream and there is no order to depend on.

And results land in a slot chosen by index, never appended. Each worker owns a disjoint run of the output and writes nothing else, exactly as TreeNBody does — so the vector that comes back is a function of (seed, count) alone. Reduce it however you like; a fold over that vector is in index order by construction.

The failure this avoids is worth naming, because it is the usual one: a Monte Carlo that draws from a shared generator gives a different answer on eight cores than on one, and the difference looks like statistical noise. It is not noise, it is the result depending on the scheduler, and no amount of averaging removes it.

use dualis_core::{Ensemble, Rng};

// A hundred thousand throws of a loaded die, in parallel.
let hits = Ensemble::new(20, 100_000)
    .with_threads(8)
    .run(|_, mut rng| u64::from(rng.unit() < 0.25));

let heads: u64 = hits.iter().sum();
// Same seed, same count, same answer — on one thread or on eight.
assert_eq!(heads, Ensemble::new(20, 100_000).run(|_, mut rng| u64::from(rng.unit() < 0.25))
    .iter().sum::<u64>());

Structs§

Ensemble
A set of independent samples to run.
Estimate
What a Monte Carlo run came back with.