Skip to main content

fuel_tensor/
reproducibility.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//! Strict reproducibility mode (ROADMAP item 13(b)).
3//!
4//! A *policy* surface over substrate that already exists: every registered
5//! kernel declares `PrecisionGuarantee::bit_stable_on_same_hardware`, and
6//! `fuel_dispatch`'s `PrecisionFloorFilter` is a HARD filter that refuses any
7//! candidate whose claim does not meet a `PrecisionRequirement`. What was
8//! missing is a way for a caller to reach it: the production realize path
9//! (`pipelined_bridge::build_optimized_graph`) never set
10//! `PlanOptions::precision_requirement`, so the default chain's floor was
11//! always unconstrained.
12//!
13//! Under strict mode the planner refuses every non-bit-stable arm. A node
14//! whose only arms are non-bit-stable on the pinned device falls back to an
15//! admissible off-device sibling when one is feasible; otherwise planning
16//! fails with `Error::FilterRejected { filter: "precision-floor", .. }` —
17//! loudly, at graph-build time, never by silently picking a non-reproducible
18//! kernel.
19//!
20//! "Bit-stable" here is the declared claim: repeat runs on the SAME hardware
21//! produce identical bytes. It is not a cross-hardware guarantee (see
22//! `docs/architecture/05-backend-contract.md`).
23//!
24//! # Scope
25//!
26//! The mode is read where the plan is BUILT, on the realize caller's thread.
27//! A scoped guard ([`strict_reproducibility`]) covers one thread and nests;
28//! [`set_global_strict_reproducibility`] covers the process. Strict wins if
29//! either is on.
30
31use std::cell::Cell;
32use std::marker::PhantomData;
33use std::sync::atomic::{AtomicBool, Ordering};
34
35use fuel_dispatch::PrecisionRequirement;
36
37static GLOBAL_STRICT: AtomicBool = AtomicBool::new(false);
38
39std::thread_local! {
40    static SCOPE_DEPTH: Cell<usize> = const { Cell::new(0) };
41}
42
43/// RAII guard returned by [`strict_reproducibility`]. Strict mode stays on for
44/// this thread until every outstanding guard is dropped. Not `Send`: the
45/// scope belongs to the thread that opened it.
46#[must_use = "strict mode ends when the guard is dropped"]
47pub struct StrictReproducibilityGuard {
48    _not_send: PhantomData<*const ()>,
49}
50
51/// Enter strict reproducibility mode on the current thread until the returned
52/// guard is dropped. Nests.
53pub fn strict_reproducibility() -> StrictReproducibilityGuard {
54    SCOPE_DEPTH.with(|d| d.set(d.get() + 1));
55    StrictReproducibilityGuard {
56        _not_send: PhantomData,
57    }
58}
59
60impl Drop for StrictReproducibilityGuard {
61    fn drop(&mut self) {
62        SCOPE_DEPTH.with(|d| d.set(d.get().saturating_sub(1)));
63    }
64}
65
66/// Turn strict mode on or off for the whole process. Composes with scoped
67/// guards: either one being on makes [`is_strict_reproducibility`] true.
68pub fn set_global_strict_reproducibility(on: bool) {
69    GLOBAL_STRICT.store(on, Ordering::Relaxed);
70}
71
72/// Is strict reproducibility in force on the current thread right now?
73pub fn is_strict_reproducibility() -> bool {
74    GLOBAL_STRICT.load(Ordering::Relaxed) || SCOPE_DEPTH.with(|d| d.get() > 0)
75}
76
77/// The precision floor the realize path must hand to the planner.
78pub(crate) fn precision_requirement() -> PrecisionRequirement {
79    if is_strict_reproducibility() {
80        PrecisionRequirement::BIT_STABLE
81    } else {
82        PrecisionRequirement::default()
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn off_by_default_is_unconstrained() {
92        assert!(!is_strict_reproducibility());
93        assert!(precision_requirement().is_unconstrained());
94    }
95
96    #[test]
97    fn scope_requires_bit_stable_and_restores_on_drop() {
98        {
99            let _g = strict_reproducibility();
100            assert!(is_strict_reproducibility());
101            assert_eq!(precision_requirement(), PrecisionRequirement::BIT_STABLE);
102        }
103        assert!(!is_strict_reproducibility());
104        assert!(precision_requirement().is_unconstrained());
105    }
106
107    #[test]
108    fn scopes_nest() {
109        let outer = strict_reproducibility();
110        {
111            let _inner = strict_reproducibility();
112        }
113        assert!(is_strict_reproducibility(), "inner drop must not end outer");
114        drop(outer);
115        assert!(!is_strict_reproducibility());
116    }
117
118    #[test]
119    fn scope_is_thread_local() {
120        let _g = strict_reproducibility();
121        let other = std::thread::spawn(is_strict_reproducibility)
122            .join()
123            .unwrap();
124        assert!(!other, "a scope must not leak to other threads");
125    }
126}