Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Determinism under parallelism

The same table and configuration produce byte-identical reports across runs and thread counts. Fixed row selection, stable ordering, and deterministic aggregation enforce this contract.

The rules

  1. No wall clock in results. Timing exists only as the opt-in deadline_seconds, and when it fires, what was skipped is recorded — the deadline changes which passes ran, never what a pass found.

  2. Seeds everywhere randomness is used. The ξ tie-breaking shuffle, the GBM holdout shuffles, the stratified sampler’s stratum offsets — all are fixed arithmetic or fixed-seed generators derived from table shape and column indices, never from entropy sources.

  3. Sorted, keyed collections in the report path. The report tree is built from BTreeMaps and sorted vectors; the JSON writer walks them in key order. Key-order iteration is insertion-order-independent.

  4. Stable tie-breaking everywhere. Every sort in the pipeline that can see ties has a final tie-break on a stable key (a column name, an index) so “equal” candidates keep a fixed order.

  5. Deterministic reduction of parallel results. Rayon work happens per column, per pair, per target — results are collected into position-indexed containers or merged through ordered maps, never accumulated into a shared float in arrival order. Where floating-point sums matter (concentration), the summation order is the sorted key order, not the parallel traversal order.

Why parallelism does not break it

Parallel passes compute one result per item and collect results in input order. Aggregation follows collection rather than occurring in a shared accumulator whose value depends on scheduling. Where a global ranking happens (dependence findings, rule selection), it sorts by (score, stable keys) before truncation, so tied items are ordered consistently when applying a cap.

The stratified sampler sample_rows(n, cap) picks row start + mix(stratum) mod stratum_width per stratum. A plain stride (row = k·j) would also be deterministic — and could repeatedly sample one weekday out of a weekly cycle. Hashed offsets vary the position within each stratum while remaining deterministic (Deterministic sampling).

What opt-in nondeterminism looks like

A deadline makes the completed work depend on runtime. It is checked between passes: a running pass completes, then later passes are skipped if the deadline has elapsed. Coverage records "deadline reached" for the skipped passes. Without a deadline, thread count and input chunk layout do not change the report bytes.

byte-identical reruns: True