pub struct SpeedGate { /* private fields */ }Expand description
Whether a wall-clock ratio measured in this build is about the SHIPPED codegen.
It is not the optimisation level: [profile.test] already carries
opt-level = 2. It is codegen LAYOUT. [profile.test.package.gam-models]
sets codegen-units = 16 and the test profile carries no LTO, while
[profile.release] is codegen-units = 1 plus thin-LTO, and the whole
margin of a compiled-vs-hand row kernel can be cross-CGU inlining. A ratio
taken in the test profile therefore measures a different program than the
one that ships, and a debug build measures fixed per-call overhead and
nothing else. Every speed gate in this workspace opens only there.
That decision is made by the TEST that opens the gate, never by this
module: test code may query its own build configuration, library code may
not (build.rs bans cfg!(debug_assertions) outside test modules, because
a library branch that only runs in one build configuration silently means
something else in the other). A gate opened in the dev lane would assert
about the wrong program, so the test returns before opening it:
if cfg!(debug_assertions) {
return; // dev lane: the codegen is not the shipped one
}
let mut gate = SpeedGate::open("RIGID-BERNOULLI-VGH-932");One speed gate: a named set of paired cells, each printed as it is measured and all asserted together at the end.
This is the ONE shape a wall-clock contract takes in this workspace, and
its call site is the marker the release lane derives the gate population
from: scripts/speed_gates.py walks the crates for every #[test] whose
body calls SpeedGate::open, resolves each to an exact test path in the
compiled release binary, runs exactly that set, and refuses a run in which
any derived gate did not execute. A gate therefore cannot be forgotten by
a name-prefix filter, cannot print ok having asserted nothing, and
cannot assert in a lane whose codegen is not the shipped one.
§Shape of a gate
// parity pins run in EVERY build, before the gate opens
if cfg!(debug_assertions) {
return; // dev lane: skip the measurement, its verdict is about the wrong program
}
let mut gate = SpeedGate::open("RIGID-BERNOULLI-VGH-932");
let timing = paired_interleaved(15, 300_000, seed, production_arm, hand_arm);
gate.faster("y=1", &timing, "production", "hand");
gate.finish();The profile check is the test’s, not the gate’s (see the module documentation above): a gate that is opened always asserts, and the dev lane does not pay for millions of timed iterations whose result it could not use because the test never opens one there.
§Two contracts, no third
SpeedGate::faster— the #932 contract: A (the compiled lowering) must be strictly faster than B (the strongest hand path or the generic tower it specialises). Loss whenmedian_ratio() <= 1.SpeedGate::not_slower— for a cell whose two arms do the same work by construction and where no speed claim is made: A must not be measurably slower than B, where “measurably” is the measurement’s OWN resolution,PairedTiming::ratio_resolution. Loss whenmedian_ratio() + ratio_resolution() < 1. There is no chosen tolerance here: the instrument reports its noise floor, and that is the only denominator a parity bar can honestly be stated in.
A gate that is opened and dropped without SpeedGate::finish panics, and
a gate finished with no cells panics: both are gates that verified nothing.
Implementations§
Source§impl SpeedGate
impl SpeedGate
Sourcepub fn open(token: &'static str) -> Self
pub fn open(token: &'static str) -> Self
Open a gate. It always asserts; the test decides whether this build is one whose verdict is meaningful before calling (see the type docs).
token is the stable, grep-able prefix every cell line of this gate
is printed under (for example RIGID-BERNOULLI-VGH-932).
Examples found in repository?
91fn main() {
92 let input: [f64; 17] = std::array::from_fn(|index| 0.35 + 0.07 * (index as f64 + 1.0).sin());
93 for (compiled, canonical) in compiled_bundle4(input).iter().zip(canonical_bundle4(input).iter()) {
94 assert!((compiled - canonical).abs() <= 1e-12 * canonical.abs().max(1.0));
95 }
96 let timing = paired_interleaved(
97 15,
98 2_000,
99 0x9320_AB,
100 batched(64, |nudge| {
101 let mut x = input;
102 x[4] += nudge;
103 compiled_bundle4(x).iter().sum()
104 }),
105 batched(64, |nudge| {
106 let mut x = input;
107 x[4] += nudge;
108 canonical_bundle4(x).iter().sum()
109 }),
110 );
111 println!("{}", timing.summary("compiled_bundle4", "nine_top_channels"));
112 // The two contracts a gate can carry, printed the way a gate prints them.
113 let mut gate = SpeedGate::open("PAIRED-TIMING-REPORT");
114 gate.faster("order=4 bundle", &timing, "compiled_bundle4", "nine_top_channels");
115 gate.not_slower("order=4 bundle", &timing, "compiled_bundle4", "nine_top_channels");
116 gate.finish();
117}Sourcepub fn faster(&mut self, cell: &str, timing: &PairedTiming, a: &str, b: &str)
pub fn faster(&mut self, cell: &str, timing: &PairedTiming, a: &str, b: &str)
Record a cell whose contract is “A is strictly faster than B”.
Examples found in repository?
91fn main() {
92 let input: [f64; 17] = std::array::from_fn(|index| 0.35 + 0.07 * (index as f64 + 1.0).sin());
93 for (compiled, canonical) in compiled_bundle4(input).iter().zip(canonical_bundle4(input).iter()) {
94 assert!((compiled - canonical).abs() <= 1e-12 * canonical.abs().max(1.0));
95 }
96 let timing = paired_interleaved(
97 15,
98 2_000,
99 0x9320_AB,
100 batched(64, |nudge| {
101 let mut x = input;
102 x[4] += nudge;
103 compiled_bundle4(x).iter().sum()
104 }),
105 batched(64, |nudge| {
106 let mut x = input;
107 x[4] += nudge;
108 canonical_bundle4(x).iter().sum()
109 }),
110 );
111 println!("{}", timing.summary("compiled_bundle4", "nine_top_channels"));
112 // The two contracts a gate can carry, printed the way a gate prints them.
113 let mut gate = SpeedGate::open("PAIRED-TIMING-REPORT");
114 gate.faster("order=4 bundle", &timing, "compiled_bundle4", "nine_top_channels");
115 gate.not_slower("order=4 bundle", &timing, "compiled_bundle4", "nine_top_channels");
116 gate.finish();
117}Sourcepub fn not_slower(
&mut self,
cell: &str,
timing: &PairedTiming,
a: &str,
b: &str,
)
pub fn not_slower( &mut self, cell: &str, timing: &PairedTiming, a: &str, b: &str, )
Record a cell whose contract is “A is not measurably slower than B”, measurable meaning beyond the paired measurement’s own resolution.
Examples found in repository?
91fn main() {
92 let input: [f64; 17] = std::array::from_fn(|index| 0.35 + 0.07 * (index as f64 + 1.0).sin());
93 for (compiled, canonical) in compiled_bundle4(input).iter().zip(canonical_bundle4(input).iter()) {
94 assert!((compiled - canonical).abs() <= 1e-12 * canonical.abs().max(1.0));
95 }
96 let timing = paired_interleaved(
97 15,
98 2_000,
99 0x9320_AB,
100 batched(64, |nudge| {
101 let mut x = input;
102 x[4] += nudge;
103 compiled_bundle4(x).iter().sum()
104 }),
105 batched(64, |nudge| {
106 let mut x = input;
107 x[4] += nudge;
108 canonical_bundle4(x).iter().sum()
109 }),
110 );
111 println!("{}", timing.summary("compiled_bundle4", "nine_top_channels"));
112 // The two contracts a gate can carry, printed the way a gate prints them.
113 let mut gate = SpeedGate::open("PAIRED-TIMING-REPORT");
114 gate.faster("order=4 bundle", &timing, "compiled_bundle4", "nine_top_channels");
115 gate.not_slower("order=4 bundle", &timing, "compiled_bundle4", "nine_top_channels");
116 gate.finish();
117}Sourcepub fn finish(self)
pub fn finish(self)
Assert that every recorded cell met its contract, naming all that did not. Consumes the gate.
Examples found in repository?
91fn main() {
92 let input: [f64; 17] = std::array::from_fn(|index| 0.35 + 0.07 * (index as f64 + 1.0).sin());
93 for (compiled, canonical) in compiled_bundle4(input).iter().zip(canonical_bundle4(input).iter()) {
94 assert!((compiled - canonical).abs() <= 1e-12 * canonical.abs().max(1.0));
95 }
96 let timing = paired_interleaved(
97 15,
98 2_000,
99 0x9320_AB,
100 batched(64, |nudge| {
101 let mut x = input;
102 x[4] += nudge;
103 compiled_bundle4(x).iter().sum()
104 }),
105 batched(64, |nudge| {
106 let mut x = input;
107 x[4] += nudge;
108 canonical_bundle4(x).iter().sum()
109 }),
110 );
111 println!("{}", timing.summary("compiled_bundle4", "nine_top_channels"));
112 // The two contracts a gate can carry, printed the way a gate prints them.
113 let mut gate = SpeedGate::open("PAIRED-TIMING-REPORT");
114 gate.faster("order=4 bundle", &timing, "compiled_bundle4", "nine_top_channels");
115 gate.not_slower("order=4 bundle", &timing, "compiled_bundle4", "nine_top_channels");
116 gate.finish();
117}Trait Implementations§
Auto Trait Implementations§
impl Freeze for SpeedGate
impl RefUnwindSafe for SpeedGate
impl Send for SpeedGate
impl Sync for SpeedGate
impl Unpin for SpeedGate
impl UnsafeUnpin for SpeedGate
impl UnwindSafe for SpeedGate
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.