Skip to content

Kernel contract: the HIP relu² stream tile at 5, 6 and 8 bits (part 1 of 3 for #3061) - #3163

Open
gilby wants to merge 6 commits into
ashhart:mainfrom
gilby:strix/nemotron-relu2-width-records
Open

gilby wants to merge 6 commits into
ashhart:mainfrom
gilby:strix/nemotron-relu2-width-records

Conversation

@gilby

@gilby gilby commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

What this changes

The HIP kernel contract checked Nemotron's relu² stream tile (affine_dot2_stream_relu2) at 4 bits only. It now runs gates 1–4 on it at every width Nemotron's oQ checkpoints store it, 4, 5, 6 and 8 bits in groups of 64, with a planted control for each wider width (the tile told 4-bit over codes packed at that width) that goes red at gate 3, and gate 5 records the 24 launches at 5, 6 and 8 bits on gfx1030, gfx1100, gfx1151 and gfx1201. No kernel source, launch or served path changes.

Correction (058439797, 1127d4390). The first version of these 24 records held the values of my box's hipcc (HIP 7.1), not ROCm 10.1's, which is the hipcc docs/kernel-contract.md says the records hold. Under ROCm 10.1 the offline audit (zig build hip-kernel-contract-limits -Dhip-relax-branches=true) reported 128 problems on this branch against main's 32: the 96 extra were exactly these 24 records on all four chips. 058439797 rewrites all 24 from the audit's own RECORD lines, and the audit is back to 32 with a list identical to main's. The gfx1100 scratch spill of the 1×8 tile that I reported as a known finding was an artifact of the HIP 7.1 compile: under the records' hipcc no width record spills on any chip, so spills_on_gfx1100 is now empty, its test asserts that no width record has scratch, and the doc paragraph, the changelog line and the source comment no longer claim a spill.

Part 1 of 3, for Nemotron 3.5 Lightning's oQ checkpoints on HIP. Part 2 (to follow) reads each matrix at its own width; part 3 (to follow) reads the MTP head file at its own width. This part stands alone: it only adds contract coverage.

Checks on this head

  • Head commit: 1127d4390: the record correction 058439797 and its wording follow-up on 46e9e1f70, which is a merge of main a3aecd8d0 into 00fc2e9d1 (b95a755ca plus the changelog number). CHANGELOG.md conflicted with main, so CI could not start; the merge keeps both sides' lines and changes nothing else. The checks below were run on 00fc2e9d1 against main 223da7659; On the merged head 46e9e1f70 against main a3aecd8d0, on the gfx1151 box: zig build test -Dhip=true --summary all 747 of 747 steps, 9,795 of 9,869 tests passed, 74 skipped (main 747 of 747, 9,794 of 9,868, 74 skipped); lean 341 and 341; zig build hip-kernel-contract, exit 1, SUMMARY gfx1151 162 kernels: 162 pass gates 1-4, 0 fail, 2 known findings; 44 controls: 44 red as planted, 0 missed; 173 limit problems (main: 159 kernels, 41 controls, 173 limit problems, exit 1); hip-kernel-test 213 passed, 6 skipped, 0 failed on both.
  • Lean checker, python3 tools/zig/lean_check.py, on the base and on this head: 341 problems on 223da7659 and 341 here, 0 new (tools/zig/lean_new.py). python3 tools/pr_check.py --base origin/main --pr 3163: 0 errors, 0 warnings.
  • Tests run: zig build test -Dhip=true --summary all: 896 of 899 steps succeeded, 13,749 of 13,868 tests passed, 116 skipped, 3 failed. Main at 223da7659: 896 of 899 steps succeeded, 13,748 of 13,867 tests passed, 116 skipped, 3 failed. The three failures fail the same way on main: dashboard_test "dashboard page polls the public stats snapshot without private details", and the Flash Next HIP host tests gather: the parked pool's parts copy the same bytes as one thread for every id count and gather: a cold call wakes the pool and the same ids gathered again stay on the caller. zig fmt --check build.zig zig and git diff --check pass.
  • Host test relu2 width records: scratch only where a known finding names it: with the list empty it fails if any width record's scratch is not zero on any chip, or if a named record stops spilling.
  • The planted controls are new kernel registrations; the comment on Relu2.plant now says gate 3, which is where kernel() plants it (.shapes).
  • CI: all checks passed on 46e9e1f70 (fmt, zig, zig-windows, zig-macos-dev-tools, pytest, benchmark-clients on Linux and Windows, release-paths; the two nightly host jobs were skipped). Main has since added changelog lines that conflict with this PR's line again; that conflict is CHANGELOG.md only.
  • Not run, and why: gfx1100, gfx1030, gfx1201 and every other HIP chip (no card; their usage comes from the contract tool's compile with ROCm 10.1's hipcc, not a run); Metal and CUDA (untouched).

Receipt

n/a: no served path changes. The new records and controls are contract coverage only; no launch, kernel, plan or loader is touched, and the 4-, 5-, 6- and 8-bit tiles are the ones main already compiles.

  • Main against branch: n/a, nothing served changes.
  • Boxes it reaches: none at run time; the HIP kernel-contract runner and gate 5 everywhere it runs.
  • New switch? None.
  • Environment: Zig 0.17.0, system hipcc (HIP 7.1, clang 21) for the device runs, ROCm 10.1's hipcc for the records and the audit, one Strix Halo iGPU (gfx1151), Linux 7.0.
  • Licence of any new weights or drafter: n/a.
Kernel contract, only when a GPU kernel is new or changed
  • Kernels registered with the contract: hip affine_dot2_stream_relu2 at 5, 6 and 8 bits in the chip's activation kind (bf16 on gfx1151, fp16 on RDNA2), each with replaces the plain stream tile then tf_nemo_relu2 at the codes' own width, as the 4-bit registration does. No kernel is new or changed; these are new registrations of a shipped kernel at widths it already serves.
  • A planted control for each new registration: control: the 5-bit relu2 stream tile reads its codes as 4-bit, and the same at 6 and 8 bits; each is red at gate 3 as planted.
  • zig build hip-kernel-contract on one Strix Halo iGPU (gfx1151), exit 1: SUMMARY gfx1151 162 kernels: 162 pass gates 1-4, 0 fail, 2 known findings; 44 controls: 44 red as planted, 0 missed; 173 limit problems. Main at 223da7659, exit 1: SUMMARY gfx1151 159 kernels: 159 pass gates 1-4, 0 fail, 2 known findings; 41 controls: 41 red as planted, 0 missed; 173 limit problems. The limit problems are main's own with this hipcc (the records hold ROCm 10.1's), the same count on both.
  • After the record correction, on the same box, gates 1–4 and controls are unchanged (162 of 162 pass, 2 known findings, 44 of 44 controls red). The limit count depends on which hipcc built the kernels that the live check loads, because the two compilers give different register counts for these tiles: with kernels built by ROCm 10.1's hipcc, 3 limit problems here and 3 on main 223da7659 (the same three: tf_moe_combine_gate, the 64-row wmma item tile, tf_vl_resize); with the system HIP 7.1 build, 197 here against main's 173, the 24 extra being these records, which no longer match the 7.1 build. Before the correction those were 27 and 173. Main's own stream-tile records fail the 7.1 live check the same way.
  • zig build hip-kernel-test: 159 of 165 passed, 6 skipped, 0 failed (main: 159 of 165 passed, 6 skipped, 0 failed).
  • Known findings: none in these records (see the correction above).
  • Chips I could not run: gfx1030, gfx1100, gfx1201 (no card).

Checklist

  • The title and description match the head commit, including the receipt and the stack.
  • New tests fail before the change, pass after it, and skip cleanly without their dependency.
  • Comments and docstrings are one line. No measurements or history in the source.
  • No personal data, machine names, internal hosts or local paths in the diff or its commits. No AI attribution lines.

Gates 1-4 run the relu^2 stream tile at every width Nemotron's oQ
checkpoints store it (4, 5, 6 and 8 bits in groups of 64), each wider
width with a planted control that reads its codes as 4-bit and goes red
at gate 3. Gate 5 records the 24 launches at 5, 6 and 8 bits on the four
RDNA chips. The 1x8 tile at those widths spills to scratch on gfx1100;
the records name it as a known finding and a host test holds the list
to the records.
@gilby

gilby commented Nov 14, 2026

Copy link
Copy Markdown
Contributor Author

A correction to this PR, found while writing records for another kernel: the 24 relu² width records I posted held my box's hipcc values (HIP 7.1), not ROCm 10.1's, which is the hipcc docs/kernel-contract.md says the records hold.

  • What was wrong. Under ROCm 10.1 the offline audit (zig build hip-kernel-contract-limits -Dhip-relax-branches=true) reported 128 problems on 46e9e1f70 against main's 32 (gfx1030 26 against 2, gfx1100 50 against 26, gfx1151 27 against 3, gfx1201 25 against 1). The 96 extra were exactly these 24 records on the four chips; nothing on main's list changed. I had only run the live check on the box, where the records matched the 7.1 build they were taken from, so it showed main's count.
  • The fix. 058439797 rewrites all 24 records, every chip column, from the audit's RECORD lines. The audit is back to 32 problems, with a list identical to main's.
  • The gfx1100 finding is withdrawn. The scratch spill of the 1×8 tile at 5, 6 and 8 bits that I listed as a known finding (point 4 of your review on nemotron hip: read oQ mixed-width MLX checkpoints (4, 5, 6 and 8 bits, a width per matrix) #3068) was an artifact of the HIP 7.1 compile. Under the records' hipcc no width record spills on any chip. spills_on_gfx1100 is now empty, its test asserts that no width record has scratch, and 1127d4390 removes the claim from the changelog line and the source comment; the doc paragraph is reworded in 058439797.
  • The live SUMMARY on gfx1151. Gates 1–4 and the controls are unchanged: 162 of 162 pass, 2 known findings, 44 of 44 controls red. The limit count depends on which hipcc built the kernels the live check loads. With kernels built by ROCm 10.1's hipcc: 3 limit problems here and 3 on main 223da7659, the same three (tf_moe_combine_gate, the 64-row wmma item tile, tf_vl_resize). With the system HIP 7.1 build: 197 here against main's 173, the 24 extra being these records, for the same reason main's own stream-tile records are in its 173. Only 7 of the 347 affine_tiles kernels compile to the same usage under both, so no record can pass both checks.

Host tests on the new head pass apart from the three that fail on main too; pr_check is clean. Parts 2 (#3242) and 3 (#3251) carry the earlier records through their merges of this branch and will take the corrected ones when this lands; neither changes a record.

@ashhart

ashhart commented Nov 14, 2026

Copy link
Copy Markdown
Owner

Thanks @gilby. The updated resource records and empty scratch list pass the host checks. The launch definitions and numerical contract are unchanged.

We will run the device check on our side to compare all 24 launch records with freshly compiled objects and run the HIP numerical contract. The real entries must retain their existing bounds and every planted control must fail. That device qualification remains before merging.

  • Synthena (Ash's Agent)

This branch has not been deployed

No deployments
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