Skip to content

[P8-06] Avoid alias-table allocations for single CPU samples - #571

Merged
ruslan-splynx merged 1 commit into
mainfrom
codex/p8-06-single-shot-sampling
Oct 13, 2026
Merged

ruslan-splynx merged 1 commit into
mainfrom
codex/p8-06-single-shot-sampling

Conversation

@ruslan-splynx

Copy link
Copy Markdown
Collaborator

Closes #556.

Each noisy trajectory used to build six state-sized probability/alias buffers for one terminal draw. CPU AoS FP64, SoA FP64 and FP32 now fully validate the state without materializing probabilities, then use one cumulative draw; zero shots validate with no allocations/RNG consumption. Two or more shots keep the alias algorithm, allocation requirements and seeded mapping.

The single-shot seed-to-outcome mapping intentionally changes. Both algorithms consume one RNG u64, so absolute noisy shot seeds, gate/channel ordering and subsequent readout RNG position are preserved. Shared validation retains normalization budgets and FP32 widening, rejects late NaN/Inf and malformed layouts before drawing, skips zero bins and handles endpoint rounding with the last positive bin. No production unsafe code, dependency, fusion or noisy-worker/state-reuse change is introduced.

Paired Criterion A/B/B/A on Intel i5-13500, logical CPU0 / one Rayon worker, shared services untouched, two repeats × 10 samples per cell:

Public API case Baseline Candidate Speedup
FP64 AoS sample n=20 / 1 shot 10.366 ms 0.820 ms 12.65×
FP64 SoA sample n=20 / 1 shot 10.308 ms 0.964 ms 10.69×
FP32 sample n=20 / 1 shot 10.212 ms 0.849 ms 12.03×
noisy n=4 / 1024 trajectories 536.0 µs 414.7 µs 1.29×
noisy n=16 / 64 trajectories 96.39 ms 83.80 ms 1.15×
noisy n=20 / 8 trajectories 366.65 ms 274.84 ms 1.33×

At n=20 single-shot, all CPU layouts drop from 7 allocations / 36 MiB scratch peak to 1 allocation / 8 result bytes. Full one-worker noisy n=20/8 additional live-heap peak drops 52 → 16 MiB; this is requested Rust heap, not RSS. Many-shot allocations match baseline exactly. Initial tiny 1024-shot regressions motivated an isolated inline(never) low-shot helper; final tiny 2–4-shot cells retain up to 5.3% (roughly 3–6 ns) overhead. No many-shot speedup or wider optimal streaming threshold is claimed.

Validation: 346 SV unit/property tests; six stored Aer noise/readout oracles; three noisy-driver tests; public analytic single/many-shot distributions through all three layouts; 1/2/4-worker noisy determinism with Pauli/Kraus/readout; million-shot convergence and FP32 equivalence. Workspace all-target clippy, final SV clippy, rustfmt and diff checks passed. Linux final release: all six noisy Aer oracles plus both public sampler/worker-invariance tests passed.

docs/perf/p8-06-single-shot-sampling.md documents seeds, limits, commands and noise-model identity. Data includes all 48 cases × 4 Criterion repeats with confidence intervals/raw samples, allocation counters, provenance and the valid initial helper campaign. An invalid shared-Cargo-target pilot returned identical binaries; allocation preflight caught it, pilot timings were discarded, and accepted builds use independent targets and distinct hashes. Benchmark/memory evidence is from actual public Rust APIs; no Python/GPU/Metal performance claim.

Draft pending CI and final review. #557 trajectory reuse/concurrency/sparse results and draft #569 Metal timings remain separate.

Share full state validation with a scratch-free one-draw cumulative path across CPU layouts. Preserve repeated-draw alias behavior and noisy shot-seed/RNG advancement; record public paired timings, allocation profiles and remaining tiny-call overhead.
@ruslan-splynx
ruslan-splynx marked this pull request as ready for review October 13, 2026 20:45
@ruslan-splynx
ruslan-splynx merged commit e51ba78 into main Oct 13, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P8-06] Avoid building CPU alias tables for one or few samples

1 participant