Skip to content

BENCH-ASSERT-CLOCK-STATE: the SM clock moves 12.8% between boots and nobody recorded it (#543, #545) - #568

Merged
localai-bot merged 6 commits into
mainfrom
row/BENCH-ASSERT-CLOCK-STATE-FIX
Aug 13, 2026
Merged

BENCH-ASSERT-CLOCK-STATE: the SM clock moves 12.8% between boots and nobody recorded it (#543, #545)#568
localai-bot merged 6 commits into
mainfrom
row/BENCH-ASSERT-CLOCK-STATE-FIX

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

merge: BENCH-ASSERT-CLOCK-STATE -- the SM clock moves 12.8% between boots and nobody recorded it (#543, #545)

On this GB10 the SM clock differs BETWEEN BOOTS with no throttling active:
median 2470 MHz on one boot, pinned flat at 2190 on the next (max 3003,
applications 2418, throttle 0x0, persistence Enabled). 12.8% clock -> +7.2% step
time. The control proves it: marlin::Marlin, 129 calls/step, byte-identical
invocation, NO source change between a170c81 and 4064558, moved
45.2845 -> 49.6544 ms/step = +9.65%.

That drift is LARGER than either per-call deficit it was used to rank (in_proj
+2.97%, out_proj/o_proj +6.28%). Those deficits are not refuted -- they were
never taken against a clock control, so they are NOT ESTABLISHED. The same effect
explains a same-binary same-arm swing of 382.60 -> 357.59 us/call across a
reboot, and two probes disagreeing ~6% uniformly eight minutes apart in one boot.

So every leg now RECORDS SM clock min/median/max/n and spread, the max and
applications clocks, the union of throttle reasons, persistence, driver, GPU
name, retained-vs-idle sample counts, and boot_id. And the summary ASSERTS:
boot_id equality between arms, within-run spread, cross-arm median offset, benign
throttle bits, persistence. A ratio that cannot be attributed to a clock state is
voided, and gate_pass requires every ratio eligible.

A first review broke it twice, end to end, and both are fixed here:

  • a window the sampler barely observed scored the CLEANEST possible record --
    over n == 1 the spread is definitionally 0.00%. Three busy samples per arm
    out of 903 passed with no reasons. The incentive was inverted: a window
    actually observed was MORE likely to be voided. Floors now require 30 busy
    samples and a 50% busy fraction, both derived from the sampler rate and the
    leg grid rather than from what happens to pass, and both surfaced in the
    report.
  • --allow-cross-boot waived the MACHINE. It passed a comparison of an
    NVIDIA GB10 on driver 580.159.03 against an H100 80GB on 550.54.15, telling
    the reader only "different boots". STATIC_FIELDS are now asserted ACROSS arms
    unconditionally, ahead of any override; the override waives boot_id alone.

24 mutations, 24 RED, restored by sha256. Two of them taught something worth
keeping: one survived because a leg-level reason already dominated it -- the
third instance of that shape today -- and one was SEMANTICALLY INERT, since
[] or [...] evaluates to the non-empty list, so a checksum proved the file
changed but not the behaviour. Both are recorded as methodology notes.

Thresholds are argued, not fitted. The 1.0% cross-arm offset rests on physics,
not on n=1: for any kernel whose time scales with clock the transfer is bounded
above by 1.0, so 1.0% offset implies <=1.0% effect, under the 2.97% smallest
deficit ranked; the measured 0.7548 sits below that ceiling as a partly
memory-bound kernel should. The 5.0% spread rule deliberately does NOT meet that
criterion, and the spec says so: passing spread establishes an arm was one state,
not that a sub-4% deficit is established.

Scope is stated where it is read, not only where it is specified: only
dgx-online-serving.sh records. finalize_*_trace.py, summarize_torch_kernels.py
and gdn_packed_component.py do not -- and the trace path is exactly where both
retracted findings came from.

tests/tools 233 -> 310, 0 removed. Preflight is green except
test_cpu_x86_llamacpp_floor, which I reproduced FAILING IDENTICALLY on a clean
origin/main checkout at load 110 and which this branch does not touch: narrowly
waived, environmental.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]

mudler added 6 commits August 12, 2026 23:48
…d no manifest records it (#543)

FOLLOWING_AGENTS_PROTOCOL

On dgx.casa, driver 580.159.03, persistence Enabled and
clocks_throttle_reasons.active = 0x0 on both sides, one boot ran the timed
window at a median 2470 MHz and the next at a flat 2190. That is a 12.79%
delta, and it repriced a byte-identical marlin::Marlin -- 129 calls/step, same
invocation, NO source change between a170c81 and 4064558 -- from 45.2845 to
49.6544 ms/step, +9.65%.

That control drift is LARGER than either deficit it was used to rank (in_proj
+2.97%, out_proj +6.28%), so both are NOT ESTABLISHED. The same effect explains
a same-binary same-arm swing of 382.60 -> 357.59 us/call across a reboot, and
two probes disagreeing ~6% uniformly eight minutes apart inside ONE boot.

Nothing in the tree records it. `grep -rn 'clocks\.' tools/ scripts/` returns
one hit, in prose. The three harness scripts that touch nvidia-smi write
-q -d PERFORMANCE,TEMPERATURE,POWER into a text blob no summary reads. No
manifest carries a clock, a boot id, or a throttle state, so no ratio in this
repository can be attributed to the clock it was measured at. Same class as
#375 and #520: an environment variable nobody wrote down, silently repricing
every number.

The spec argues both thresholds from the data rather than from taste. Within-run
spread 5.0%: it must ACCEPT the only clean window we have, (2489-2398)/2470 =
3.68%, and REJECT the within-boot disagreement at ~26%. Cross-arm median offset
1.0%: at the measured transfer of 0.754 points of kernel time per point of clock
that estimates to ~0.75%, under the 2.97% smallest deficit anyone ranks. The
transfer is n = 1, is reported and never gated on, and is recorded as owed.

No measurement is taken here and none is restated. #545 is linked because the
box's MTBF is now shorter than one four-leg chain, which is why a cross-boot
override exists at all -- it waives identity, never state.

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]
…ross-boot ratio (#543)

FOLLOWING_AGENTS_PROTOCOL

One helper, tools/bench/gpu_clock_state.py, does the sampling, the folding and
the assertions; other harnesses import it. Standard library only, like
serve_low_common, so every assertion runs in CPU CI with no GPU and no
nvidia-smi -- the 50 helper cases use synthetic manifests and a stub probe.

RECORDED per leg, beside memory/, by a background sampler across the timed bench
loop: the SM clock over the window (min/median/max and n), clocks.max.sm,
clocks.applications.graphics, the union of active throttle reasons, persistence
mode, and the boot id. Idle samples are EXCLUDED from the statistics and
COUNTED, never silently dropped -- a clock read while the GPU does nothing
priced no work, and the window necessarily contains the harness's own gaps
between concurrency points. An entirely idle window has nothing to attribute and
is refused.

ASSERTED in online_gate_summary through the existing `reasons` seam, which is
this harness's spelling of NOT ESTABLISHED, so nothing new is invented and no
gate is weakened: a cross-boot pair is refused; a within-run spread above 5.0%
or a cross-arm median offset above 1.0% voids the ratio; a non-benign throttle
bit or persistence-off voids the leg; an arm whose three legs straddle two boots
will not fold. Every ratio carries a clock block with both medians, both
spreads, the signed offset and the estimated effect, and the report prints it
next to the verdict, so a reader can size the clock against the effect without
leaving the row.

--allow-cross-boot waives IDENTITY, never STATE. It exists because #545 makes
same-boot capture of a four-leg chain unreliable and a gate nobody can satisfy
is a gate everybody routes around; the spread and offset rules still apply and
the comparison is stamped with a recorded caveat rather than passing silently.

Consequence worth stating rather than discovering: re-summarizing an existing
evidence tree now yields NOT ESTABLISHED, because no tree on disk carries a
clock record. That is the correct answer -- those trees genuinely cannot be
attributed to a clock -- and it is why the next commit adds a note instead of
editing any recorded number.

233 -> 295 tests, 0 removed, proven by a sorted test-name diff. Twelve mutations
with count == 1 anchors, restored byte-for-byte by sha256. THREE SURVIVED the
first round: both ratio-level clock terms and the missing-record reason. #520's
lesson repeating -- the leg-level reason already voided every gate assertion, so
each ratio-level site was dominated, and a single gate_pass assertion let the
throughput and memory ratio families mask each other's removal. Two cases now
assert the two families' binding_eligible SEPARATELY on a pair whose arms are
individually clean, and a third pins the text that names the offending arm,
which is the only thing the reader has. Twelve of twelve RED.

The trace/per-kernel harnesses are NOT wired yet and are recorded as owed in the
spec. That is the path #543's retracted findings came from, so it matters that
it is named rather than assumed covered.

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]
…y which numbers predate the assertion (#543)

FOLLOWING_AGENTS_PROTOCOL

benchmarking.md gains the method: what a leg records, why two arms on different
boots are not comparable, and the operational fix. Clocks can be pinned with
`sudo nvidia-smi -lgc <freq>` and released with `-rgc` -- passwordless sudo is
available on dgx and -lgc is supported there.

Pinning is a SHARED-HOST MUTATION and must not be done while another session
holds $HOME/gpu.lock: it would silently reprice their in-flight measurement,
which is exactly the defect the section exists for. It is recommended as a
pre-measurement step UNDER the lock, not as a standing configuration -- leaving
the box pinned makes every later run inherit a state nobody recorded, which is
where this started.

NO RECORDED NUMBER IS EDITED. AGENTS.md: never delete evidence. Instead each
surface that cites the old figures says they predate clock assertion --
BENCHMARKS.md as an at-a-glance row (the prose there is at its paragraph and
cell budget, so the note goes where a result belongs, in a table row), and
STATUS.md next to the parity-pin note that already explains a different
attribution defect on the same runs. Neither withdraws nor restates anything:
these numbers simply carry no clock, so a difference of a few percent between
two of them is not established BY THEM ALONE.

benchmark-record.md, which is the append-only log, carries the forensics: the
two-boot table, the marlin control, the two findings it retracts (in_proj +2.97%
and out_proj +6.28%, neither ever taken against a clock control), the thresholds
and their derivation, and the live state at the time of writing. A read-only
probe on 2026-08-12 returned a THIRD boot id, 13dc5579, at the degraded 2190 MHz
with clocks.max.sm 3003 -- the defect is live, not historical.

No clock was pinned and no GPU work was queued in this row: another session held
the lock.

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]
Carries fafa16f (Nemotron35LightningSnapshot declaration order, #556) and
d861819 (DSA top-k bounds, #505) onto the review-fix branch. No conflict: the
merged paths and the clock-state paths are disjoint.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]
…ct 0.00%, and the override waived the machine (#543, #545)

Four review findings against row/BENCH-ASSERT-CLOCK-STATE. The design, seam,
records discipline and the twelve original mutations stand; these are defects in
what the assertions cover.

F1. Idle dilution. `validate_clock_record` required only `n >= 1`, and
`spread_pct` over `n == 1` is definitionally 0.00% -- the BEST score the gate can
award -- so the window the sampler barely observed outscored the one it watched.
Six legs each holding ONE busy sample and 300 idle gave `gate_pass: true`,
`clock reasons: []` and a report line reading `+0.00%`. `idle_samples_excluded`,
the one field that would have betrayed it, was written to `r<N>.summary.json` and
then never asserted, never folded into the ratio's `clock` block and never
printed. `clock_reasons` now floors both the retained busy count (30) and the
busy fraction (50%), and both counts are carried in the clock block and printed
on the report's `observed:` line. The floors are derived from the sampling rate
and the grid: at `--interval 1` a busy sample is a second of OBSERVED BUSY GPU,
and the smallest configured leg (1920 sequential decode steps plus 48 prefills of
1024 tokens) would have to average under ~16 ms/step to finish inside 30 of
them, against 82-88 ms/step measured on this box. 30 also sits 40% below the
smaller of the two real #543 windows (n=61, n=50), so it accepts both.

F2. `--allow-cross-boot` waived hardware identity as a side effect.
`compare_clock_records` never compared `gpu_name`, `driver_version`,
`clocks_max_sm_mhz`, `clocks_applications_graphics_mhz` or `persistence_mode`
ACROSS the arms; `STATIC_FIELDS` was enforced only within a window and between
one arm's legs. Same-boot equality was the implicit proxy for "same machine", and
the override removed it with nothing in its place: an NVIDIA GB10 / 580.159.03 /
max 3003 arm compared CLEAN against an NVIDIA H100 80GB HBM3 / 550.54.15 / max
1980 one, caveated only as "different boots". `STATIC_FIELDS` is now asserted
across the arms unconditionally. #545 makes the override the normal path, so this
was reachable, not theoretical.

F3. The test named "the override does not waive state" was dominated. Rewriting
`compare_clock_records` to `reasons = [] if allow_cross_boot else [...]` (R15)
survived the full suite GREEN: one test asserts an OFFSET reason, appended
outside the mutated expression, and the other writes an over-spread LEG already
voided at leg level by `_clock_for_leg`. Exactly one check lives only at the
compare site -- the merged-arm spread, an arm whose three legs each sat flat at a
different clock -- because `merge_clock_records` raises only on a straddled boot
and on a static field. A summary-level case now pins it: three individually-flat
legs at 2470 / 2300 / 2190 on ONE boot under `allow_cross_boot=True`, with the
vLLM arm at the merged median so the offset stays 0.00% and cannot mask the
removal. R15 is now RED.

F4. The sampler was orphaned on every abort path. `clock_pid` was `local` to
`run_leg` and invisible to the EXIT trap, which reaps only `profiled_pid`,
`spid` and `mpid`; under `set -euo pipefail` a failing `online_gate.py bench`
exits without reaching `stop_clock_sampler`. The sampler had neither `--pid` nor
`--max-duration`, so its only stop condition was a SIGTERM that path skips, and
it went on polling `nvidia-smi` once a second forever on a box another session
may hold `$HOME/gpu.lock` on. The spec claimed "the same shape as the memory
sampler"; it was not, and it now is on BOTH counts -- `clock_pid` is a global
reaped by `cleanup_server`, and the sampler is bounded by `--max-duration`
(7200 s, 4x the driver's own readiness budget, a bound on an orphan and not a
budget on a leg).

F5. The two thresholds were argued to different standards. The 1.0% offset was
derived forward through the n=1 transfer; the same criterion was never applied to
spread, where 5.0 x 0.7548 = 3.77% exceeds the 2.97% smallest deficit ranked.
Spread is NOT tightened -- the forward criterion would demand <=3.93%, which sits
0.25 points above our only clean capture (3.68%) and would void it on a
noisier-but-healthy day -- so the reason it may exceed is stated instead: the
offset bounds a SYSTEMATIC arm-to-arm difference that transfers whole into the
ratio, while spread bounds DISPERSION inside one arm's window, most of which is
common to both arms and whose residual is the difference of two medians that the
offset rule already bounds. The residual is recorded: passing spread establishes
that an arm was ONE state, not that a sub-4% deficit is established. The offset
argument is also strengthened off the n=1 coefficient entirely: for any kernel
whose time scales with clock the transfer is bounded above by 1.0, so a 1.0%
offset implies at most a 1.0% effect on PHYSICS, still under 2.97%. The measured
0.7548 sits below that ceiling exactly as a partly memory-bound kernel should.
The coefficient is not a gate TERM (proven by the mutation set) but it was a gate
PREMISE; the physics bound retires it from that role.

F6. `.agents/benchmarking.md` -- the file an agent reads before measuring --
claimed "Every leg records..." and "other harnesses import it..." in the present
tense with no caveat. Only `dgx-online-serving.sh` records anything;
`finalize_*_trace.py`, `summarize_torch_kernels.py` and `gdn_packed_component.py`
are unwired, and that trace path is exactly where both retracted findings came
from. The guide now says so, matching the spec's own Scope and Owed.

Recorded, not fixed, in the spec's Owed: `all-runs.json` carries no clock block
and no `allow_cross_boot` flag (report.md does print `(OVERRIDDEN)`/`CAVEAT:`,
so it is not buried for a human, but the JSON a consumer parses is silent);
`compare_clock_records` builds keys as `f"{ours_label}_boot_id"`, so identical
labels would collapse one arm into the other, unreachable from current call
sites; and the busy floors are derived but not yet measured against a real leg.

Gates. `python3 -m unittest discover -s tests/tools -t .`: 295 -> 310, exit 0,
0 removed, proven by a sorted test-name diff. 24 mutations (the original 12 plus
R13-R24), one at a time, `count == 1` anchors, restored byte-for-byte and
verified by sha256: 24/24 RED. R17 survived the first pass and was a genuine gap
in the new validation, not a dominated site, so two cases now pin it; M11 first
read SURVIVED because the mutation itself was inert (`[] or [...]` is the
non-empty list), which is why a byte-level sha256 proves the file changed and not
that the behavior did. Both reviewer bypass probes re-run and now CAUGHT.
`bash -n` and `shellcheck -S warning` clean on the driver.
`scripts/agent-preflight.sh --staged` clean. No GPU work queued and no clock
pinned: another session may hold `$HOME/gpu.lock`.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]
Keeps the PR current. This row's own changes are python/docs/shell only and touch
no C++; the windows-msvc failures on the stale PR head came from main's side.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [ClaudeCode]

# Conflicts:
#	.agents/benchmark-record.md
@localai-bot
localai-bot merged commit 51ec6be into main Aug 13, 2026
22 of 24 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.

2 participants