API reference¶
Everything on this page is generated from the source docstrings.
Top level¶
shapesandstrides.measure
¶
measure(fn: Callable[[], object], *, warmup: int = DEFAULT_WARMUP, iters: int = MIN_ITERS, device: int = 0, flush_l2: bool = True, policy: ClockPolicy | None = None, min_duration_us: float = MIN_DURATION_US) -> TimingResult
Time a callable honestly.
Returns an interval and a quality tier, never a bare number.
min_duration_us sets the floor for the timed window (see resolve_inner_reps). It exists to make CUDA event quantization small relative to the effect size we claim to detect, not merely to clear the timer's own floor for registering an event at all: a window barely above the timer's resolution still ties heavily, and a bootstrap CI over tied data can land narrower than the timer can actually resolve. As a second line of defense, the CI is widened to at least one quantization step below (see quantization_step in shapesandstrides.stats).
Known limitation: the reported CI is a bootstrap over samples within a single measurement window, so it captures sampling error inside that window but not run-to-run variability between windows. On unlocked hardware the cross-run spread can exceed the reported interval by orders of magnitude — scripts/validate_timing.py measures exactly this. Folding between-window variance into Tier B intervals is planned for Phase 1.
Source code in src/shapesandstrides/timing.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | |
shapesandstrides.compare
¶
compare(candidate_fn: Callable[[], object], baseline_fn: Callable[[], object], *, warmup: int = DEFAULT_WARMUP, iters: int = MIN_ITERS, device: int = 0, flush_l2: bool = True, policy: ClockPolicy | None = None, min_duration_us: float = MIN_DURATION_US) -> ComparisonResult
Measure a candidate against a baseline, interleaved.
The two callables alternate inside a single measurement window rather than running as two separate windows. GPU clocks drift, and a drift between two sequential windows lands entirely in the ratio: measured on an unlocked laptop, comparing identical work that way gave a p90 error of 106% and a worst case of 141%. Interleaved, the same comparison gave a p90 error of 1.0%.
The baseline is still measured fresh on every call and never cached. Interleaving strengthens that rule rather than replacing it: the two sides now share not just a process but a thermal and clock state.
This is a thin CUDA-gated shell: it collects the raw samples via _interleaved_samples and hands them to _compare_impl, which does the actual guard/CI/ratio logic and needs no GPU to test.
Source code in src/shapesandstrides/timing.py
Result types¶
shapesandstrides.TimingResult
¶
Bases: BaseModel
A timing measurement.
Deliberately defines no float, int or index: a caller must not be able to collapse this into a bare number and lose the interval.
Source code in src/shapesandstrides/types.py
shapesandstrides.ComparisonResult
¶
Bases: BaseModel
A candidate measured against a baseline timed in the same session.
The baseline is never cached across runs. Re-measuring it every time is what lets us tell "my kernel regressed" from "torch got faster", and it is what makes the ratio comparable across machines and architectures.
Source code in src/shapesandstrides/types.py
shapesandstrides.MeasurementTier
¶
Bases: str, Enum
How much the numbers in a result can be trusted.
A: clocks locked and verified stable. Full verdicts, drift-eligible. B: clocks floating, variance measured and folded into the interval. C: unstable or throttled. No performance verdict is valid.
Source code in src/shapesandstrides/types.py
shapesandstrides.EnvironmentFingerprint
¶
Bases: BaseModel
Identifies the toolchain and device a run happened on.
Two runs are only comparable when their fingerprints match exactly.
Source code in src/shapesandstrides/types.py
Clock policies¶
shapesandstrides.clocks.UnlockedClockPolicy
¶
Measure without pinning. Honest, and the only option on most machines.
Source code in src/shapesandstrides/clocks.py
shapesandstrides.clocks.LockedClockPolicy
¶
Pin the SM clock, and optionally the power cap, verifying by readback.
Source code in src/shapesandstrides/clocks.py
shapesandstrides.clocks.ClockLockError
¶
shapesandstrides.clocks.assign_tier
¶
Classify a measurement window.
Throttle flags alone are not sufficient: on an RTX 3060 laptop the SM clock swung 495 MHz (5.1% CV) while the flags stayed silent, and two identical runs disagreed on whether throttling fired at all. Observed variance is the governing signal.
Only hw_throttled and observed clock variance gate the tier —
nothing else. The rule: hardware-asserted throttling disqualifies a
measurement; driver-reported software flags are recorded but do not,
because they were measured stuck Active at idle on consumer
hardware. Concretely: hw_throttled is true when either
hw_thermal_slowdown or hw_power_brake_slowdown fired — both are
asserted by the GPU's own hardware safety circuits, not by software
policy, so either one alone disqualifies a window. Every software
throttle flag we tried turned out to be untrustworthy: measured on real
consumer laptop hardware, sw_power_cap and sw_thermal_slowdown
were both Active at idle — 55C, 18W, the card cold and doing nothing.
A flag stuck on at idle is not evidence of anything, so driver/vendor
software policy is excluded entirely, and stable observed variance is
what governs everything else. Software throttle activity is still
recorded on TimingResult (power_capped, sw_thermal_flagged) as
metadata, never as a gate.
Source code in src/shapesandstrides/clocks.py
Statistics¶
shapesandstrides.stats.bootstrap_ci
¶
bootstrap_ci(samples: list[float], confidence: float = 0.95, n_resamples: int = 2000, seed: int = 12648430) -> tuple[float, float]
Percentile bootstrap CI of the median.
Seeded so a given sample set always yields the same interval — a reproducibility requirement, not a convenience.
Source code in src/shapesandstrides/stats.py
shapesandstrides.stats.ratio_ci
¶
ratio_ci(candidate: list[float], baseline: list[float], confidence: float = 0.95, n_resamples: int = 2000, seed: int = 12648430) -> tuple[float, float]
CI of speedup = median(baseline) / median(candidate).
Values above 1.0 mean the candidate is faster. Resampling both sides independently propagates uncertainty from each into the ratio, which a naive ratio-of-medians throws away.
Source code in src/shapesandstrides/stats.py
shapesandstrides.stats.percentile
¶
Linear-interpolated percentile. p is in [0, 1].
Source code in src/shapesandstrides/stats.py
shapesandstrides.stats.cv_percent
¶
Coefficient of variation as a percentage. 0.0 for a zero mean.
Source code in src/shapesandstrides/stats.py
Environment¶
shapesandstrides.env.capture_fingerprint
¶
Source code in src/shapesandstrides/env.py
shapesandstrides.env.arch_family
¶
Source code in src/shapesandstrides/env.py
Telemetry¶
shapesandstrides.telemetry.ClockSampler
¶
Samples SM clock and throttle state cheaply, or not at all.
If NVML is unavailable we collect NO clock evidence rather than collecting bad evidence. Tier A requires clock evidence, so a host without NVML can never reach it. That is the intended, conservative degradation.
Source code in src/shapesandstrides/telemetry.py
throttled_now
¶
True if the hardware thermal assertion is currently set.
Checks only HwThermalSlowdown (bit 0x40) — the GPU's own hardware safety circuit — not any software-reported reason. Measured on real consumer laptop hardware: SwPowerCap (0x4) and SwThermalSlowdown (0x20) were both set at idle, 55C, 18W, card cold and doing nothing. A software flag stuck on at idle is not evidence of anything, so no software reason is trusted here, including the generic HwSlowdown (0x8) parent bit, which aggregates HwThermalSlowdown with HwPowerBrakeSlowdown and so is not the unambiguous hardware-thermal signal by itself. Only the specific thermal bit gates; everything else is metadata sampled separately from the before/after nvidia-smi snapshot in shapesandstrides.timing.