Skip to content

fix(gpu-gate): assert the sm_80-gated lanes ran, and correct three stale coverage claims - #236

Merged
TobiBu merged 2 commits into
mainfrom
fix/gpu-gate-sm80-blind-spot
Aug 27, 2026
Merged

fix(gpu-gate): assert the sm_80-gated lanes ran, and correct three stale coverage claims#236
TobiBu merged 2 commits into
mainfrom
fix/gpu-gate-sm80-blind-spot

Conversation

@TobiBu

@TobiBu TobiBu commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Two commits: the stale numbers, then the gate.

1. Three stale coverage claims (175dc53)

distributed/fmm.py is 31% on CPU, not 19%. It moved without a card#231 and #232
added a partitioner-config test and relocated the halo-exchange resolver test out of
tests/distributed/ (where it was skipped below 2 devices) into tests/unit/. So D.3's
"structurally unreachable" rows were a ceiling on what CPU reaches, not a floor —
including the two rows that table got right.

The third is the bad one, because it's inside bench/gpu_gate.py: its rationale still
described F27's two files as "both at 0% coverage", four lines after warning that "a stale
number in a docstring reads as a check that is being performed." They're 91% and 100%.

2. The gate's blind spot (26f84b6)

_MUST_RUN held three file fragments, all gated on jax.default_backend() != "gpu".
That catches a CPU fallback and nothing else.

Five tests gate on sm_80 instead, via pallas_m2l_{real,complex}_fused_supported(). On
a real GPU that isn't Ampere+, the three backend checks pass, those five self-skip, and the
gate prints green having validated no Pallas kernel outside interpret mode — one of the
three things its own docstring claims it covers.

They're the tests docs/handoff_g10_gpu_validation.md calls "the headline item — the whole
reason this handoff exists"
, and that document warns in as many words that they "self-skip
off sm_80, so a run on the wrong card looks green while asserting nothing."
The warning was
written down. The gate was built without it.

Why node-id fragments, not file fragments

Two things the file-level form gets wrong here:

  • the module's other ~48 tests run on CPU, so a file fragment always finds a passing test and
    reports "not vacuous" regardless of what skipped;
  • ..._in_gradient is parametrised on interpret, and [True] runs in interpret mode on
    any card. Only [False] reaches the real Triton kernel, so the [False] is load-bearing.

Tests

  • Recorded fixtures now carry the fused lanes, since a real gate run does.
  • NON_AMPERE_OUTPUT is the blind spot itself — backend tests green, all five lanes skipped
    — and must produce five complaints, each naming sm_80.
  • One test pins the parametrisation trap: [True] passing must not excuse [False] skipping.
  • The drift guard is the one that matters. A stale fragment already fails loudly (it
    matches nothing → "0 tests ran"). The way this blind spot actually formed was a test being
    added and never registered — the fifth, fp32-on-the-fused-lanes, landed after the handoff
    declared that gap open. So the guard derives the sm_80-gated set from the test module's
    AST and fails if any is unregistered.

I verified the guard bites rather than passing vacuously: the AST scan finds exactly 5,
the registry holds 5, and dropping one registration is detected.

Also corrects the handoff, which still said "four tests" and still listed the fp32 fused-lane
gap as open.

Verification

black --check .                1100 files unchanged
isort --check-only .           clean
pre-commit run --all-files     black / isort / pydoclint / flake8 all Passed
JAX_ENABLE_X64=1 pytest        1379 passed, 93 skipped   (+6, the new gate tests)
pytest tests/characterization  34 passed                 (golden did not move)

No jaccpot/ production code touched — bench/, tests/ and docs only.

This does not make the gate green on a non-Ampere card — it makes it honest about not being green. That's the intended behaviour: a release shouldn't be certified by a run that never compiled the fused kernels.

🤖 Generated with Claude Code

@TobiBu
TobiBu force-pushed the fix/gpu-gate-sm80-blind-spot branch 2 times, most recently from 9a735a4 to e59a095 Compare August 26, 2026 22:37
@TobiBu

TobiBu commented Aug 27, 2026

Copy link
Copy Markdown
Owner Author

pre-commit.ci run

Tobias Buck and others added 2 commits August 27, 2026 11:06
distributed/fmm.py is 31% on CPU, not 19%. It moved without a card: #231 and
test out of tests/distributed/ (skipped below 2 devices) into tests/unit/. So
D.3s "structurally unreachable" rows were a ceiling on what CPU reaches, not a
floor -- even the two rows that table got right.

The third is worse, because it is inside bench/gpu_gate.py: its rationale still
described F27s two files as "both at 0% coverage" while warning, four lines
earlier, that a stale number in a docstring reads as a check being performed.
They are 91% and 100% on CPU, and the gate is what proved a GPU was never the
blocker.

Docs and one module docstring only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-gated ones

The gate exists to stop a vacuous GPU run printing green. Its non-vacuity list
held three file fragments, all gated on jax.default_backend() != "gpu" -- so it
caught a CPU fallback and nothing else.

Five tests gate on sm_80 instead, via pallas_m2l_{real,complex}_fused_supported().
On a real GPU that is not Ampere+ the three backend checks pass, those five
self-skip, and the gate reports green having validated no Pallas kernel outside
interpret mode -- which is one of the three things its own docstring claims it
covers. They are the tests docs/handoff_g10_gpu_validation.md calls "the headline
item -- the whole reason this handoff exists", and that document warns in as many
words that they "self-skip off sm_80, so a run on the wrong card looks green
while asserting nothing". The warning was written down; the gate was built
without it.

_MUST_RUN_SM80 holds node-id fragments rather than file fragments, for two
reasons the file form gets wrong: the module's other ~48 tests run on CPU and
would satisfy a file-level check no matter what skipped, and
..._in_gradient[True] runs in interpret mode on any card, so only the [False]
half is evidence that the Triton kernel ran.

Tests. The recorded fixtures now carry the fused lanes, since a real gate run
does. NON_AMPERE_OUTPUT is the blind spot itself: backend tests green, all five
lanes skipped, and it must yield five complaints. One test pins the
parametrisation trap -- [True] passing must not excuse [False] skipping. The
drift guard matters most: it derives the sm_80-gated set from the test module's
AST and fails if one is unregistered, because the way this blind spot formed was
a test being added and not registered (the fifth, fp32-on-fused-lanes, was added
after the handoff said that gap was open). Verified it bites: dropping one
registration is detected.

Also corrects the handoff, which still said four tests and still listed the fp32
fused-lane gap as open.

1379 passed, 93 skipped; characterization 34 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@TobiBu
TobiBu force-pushed the fix/gpu-gate-sm80-blind-spot branch from e59a095 to b29f5cb Compare August 27, 2026 09:35
@TobiBu
TobiBu merged commit ee26e25 into main Aug 27, 2026
11 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.

1 participant