Repository navigation
feat(rocke): top-left causal and attention band coverage on gfx950 - #13125
Conversation
✅ All Checks Passed — Ready for Review
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
|
🎉 All checks passed! This PR is ready for review. |
dlangbe
left a comment
There was a problem hiding this comment.
the new mask bodies have no spec→IR coverage. KERNEL_AUTHORING.md "Compliance & hard invariants" (1) requires library attention emission changes to be mirrored in the C++ engine (platform/cpp/instances/ carries the unified and tiled 2D/3D bodies), with .py/.c emit pairs per config. this PR touches nothing under platform/ or library/tests/parity/:
grep -rn "causal_top_left\|right_bound" platform/ library/tests/parity/returns nothing.attention_tiled_2d_ctx_prologue.cpp:334still hard-codescontext_len = seq_len - cur_batch_q_len.
the platform golden only holds default-mask cases, and deeab72 dropped the library golden. so the _tl / _rbu / _rb<R> / non-causal-window IR on 2D, 3D, scalar and dense is pinned by nothing. the next refactor of any mask site can move it, and only a GPU lane would notice. separately, the risk assessment still says default-off IR is "pinned byte-identical by a new golden", which no longer matches the testing section.
either add the C++ mirror plus emit-pair configs (tl, rbu, rb, left-only window) to gfx950_attention_tiled_{2d,3d}_emit and attention_unified_emit, or at minimum add those variants as representative-IR golden cases and list the C++ mirror as an explicit follow-up in the PR body so the divergence between the two engines is tracked.
6d15053 to
c2bb6b2
Compare
c2bb6b2 to
0df4cc2
Compare
Pre-commit check failed⛔ pre-commit failed Please run locally:
This repo uses |
4597af4 to
e08e170
Compare
cgmillette
left a comment
There was a problem hiding this comment.
PR #13125 — top-left causal and attention band coverage on gfx950 (AnaghaRaoAMD, AICK-2505) — 🟢 ACCEPT: thorough; gfx942 lane first
| Prior item | Status |
|---|---|
| dlangbe: new mask IR unpinned; C++ mirror required | 🟡 PARTIAL — 26 golden cases match ×3 flavors (ran); C++ mirror deferred, no ticket |
| dlangbe: unified equal-length top-left fold | 🟢 FIXED — fold only for dense; gfx950 TL → _tl (ran) |
| dlangbe: dense empty q-blocks read next batch | 🟢 FIXED — start tile clamped + rows zeroed; band matrix at batch=2 |
| dlangbe: stale NO_MASK test comment | 🟢 FIXED — scoped to gfx942/gfx1250 |
| yraparti: one normalized band | 🟢 FIXED — normalize_band → AttentionBand |
| yraparti: band index truth tables | 🟢 FIXED — unified + dense truth tables (GPU) |
| yraparti: NO_MASK arch-dependent / silently causal | 🟡 PARTIAL — gfx950 exact; gfx942/gfx1250 legacy causal (documented; #13211) |
yraparti: RAG_KBOUND missing in window loops |
⚪ Unreachable — spec rejects ragged + window (ran); now commented |
| yraparti: tuning band validity / cache keys | 🟡 PARTIAL — identity/keys + gfx942 decline tested; window/tile validity untested |
| yraparti: d256 names, sw suffix, loose inputs (×8) | 🟢 FIXED — suffixes present; bad alignment/window/mixed vocab rejected (ran) |
| Bots / CI | 🟡 Pre-commit green; TheRock green at a7b95c3a, head pending; gfx942 GPU lane unrun |
| Our checks | 🟢 Merge clean; default-off IR identical; no PR regressions (ran) |
| # | Sev | file:line | Finding |
| yraparti: d256 names, sw suffix, loose inputs (×8) | 🟢 FIXED — suffixes present; bad alignment/window/mixed vocab rejected (ran) |
| Bots / CI | 🟡 Pre-commit green; TheRock green at a7b95c3a, head pending; gfx942 GPU lane unrun |
| Our checks | 🟢 Merge clean; default-off IR identical; no PR regressions (ran) |
| # | Sev | file:line | Finding |
|---|---|---|---|
| N1 | 🟡 | dispatch/attention/common.py:720-729 |
SLIDING_WINDOW+W, default right: gfx950 now non-causal top-left, gfx942/1250 reject — not in Risk (ran) |
Utility: 🟢 Positive — exact cuDNN band semantics on gfx950; rejects instead of mis-masking.
Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good
…mily does not serve #13150 builds a unified problem for the gfx1151 / RDNA launch grid. With the band normalisation that raised for a SLIDING_WINDOW request that carries its bounds in window_left / window_right. _attention_band now returns the default mask for those requests, so the problem is only a geometry carrier. JIRA ID : AICK-2505 Co-Authored-By: Claude <noreply@anthropic.com>
3d871e8 to
996c351
Compare
…pes report test Develop's gfx950 band coverage (#13125) makes the registry accept seqlen_q=100, seqlen_k=77. The other declined cases still cover the category.
The tests pinned rocKE's admission decisions, decline text and exact category counts, so a rocKE coverage change (develop #13125) failed them. A small synthetic registry now states the behaviour each case needs; one live-registry smoke checks only tool-owned facts.
… for the gfx950 dense-attention ingestor catalog (#13024) ## Summary Makes the rocKE dispatcher registry the single source of truth for the gfx950 dense-attention ingestor catalog (`hipkernel:Gfx950AttentionDense`, 840 kernels, unchanged), so drift between the registry and the shipped catalog fails a test. The IngestorGenerator gates used to maintain the catalog now refuse input they cannot verify. Builds on #13593. JIRA ID : AICK-2513 ## Risk Assessment Risk 3. Most of the change is developer tooling plus a build-time `hkp_pack` pre-flight; the shipped catalog regenerates with no differences and no engine C++ changes. The rocKE gfx950 dense predicate gains an LDS-capacity gate and a `block_n=256` tile. The branch is merged with current develop, whose gfx950 dense kernel changes (#13125) are packed into this engine, so this PR also carries a gfx950 hardware run (below). ## ASIC Coverage gfx950 only. The predicate and tile changes affect the gfx950 dense catalog; everything else is host-only. Required before merge: PR CI and one gfx950 run of the dense engine (done at `75c5a107cb`; later commits change tests only). Other architectures are covered by PR CI: their catalogs do not change, and CI packs them through the same pre-flight. ## Testing Summary - **Host (Python):** IngestorGenerator, descriptor-packaging and rocKE attention suites; dense catalog regeneration from the selection and from the manifest. - **Host (C++ and CTest):** superbuild with the CI flags (`GPU_TARGETS=gfx950`, ROCKE, kernel ingestor, SDPA, packaging probes ON), provider unit tests with the GPU hidden, and the pack, probe, census and test-name lanes. - **gfx950 (MI355X):** dense `SdpaFwd` integration (`quick`, `standard`, GPU reference) with support claims enforced, gfx950 attention unit tests, census. ## Testing Checklist All at this head unless noted, Linux, host tests with `HIP_VISIBLE_DEVICES=-1`. - [x] Superbuild, CI flags - `ninja` - 0 warnings - Status: Passed - [x] IngestorGenerator - `pytest tests` - 1,150 passed, 9 skipped (flatbuffers headers absent) - Status: Passed - [x] Descriptor packaging - `pytest descriptor-packaging/tests` - 697 passed, 1 skipped; `TestRealArchiveReaders` also passes without PyYAML - Status: Passed - [x] rocKE attention - `pytest tests/test_attention_dense_gfx950_lds.py tests/test_attention_spec_predicate_parity.py tests/dispatch/attention` - 623 passed - Status: Passed - [x] Provider unit tests - `hip_kernel_provider_tests` - 1,087 passed; `*Gfx950Attention*` 167 of 167 - Status: Passed - [x] CTest - `ctest -R 'hkp-pack|hkp-probe-|hkp-census-|_test_name_validation'` - 29 of 29 - Status: Passed - [x] Dense catalog regeneration - `catalog_diff --strict-spec` (selection) and `--subset` (manifest) - no differences - Status: Passed - [x] Installed tree - `rocke_library_attention_cpu_pytest`, `rocke_library_attention_pytest` - 35 passed; 600 passed - Status: Passed - [x] gfx950 hardware - dense `SdpaFwd` `quick` 8, `standard` 45, GPU reference 45 (0 broken, 0 unclaimed), `*Gfx950Attention*` 167, `hip_kernel_provider_tests` 1,148, census 10 of 10 - Devices: MI355X - Status: Passed (at `75c5a107cb`; later commits change tests only) - [ ] PR CI - GitHub PR checks - Status: Pending Not covered: the rocKE gfx950 numeric tests (`rocke_library_attention_gpu_pytest`) need a ROCm torch that no CI image has; the IngestorGenerator suite runs in no CI job yet. ## Technical Changes - **Registry as source of truth.** `configs/gfx950_attention_dense.engine.yaml` (manifest) and `configs/gfx950_attention_dense.yaml` (selection) replace the hand-authored profile. `registry_enumerator.py` expands the manifest through the dispatcher; `test_registry_regeneration.py` fails on drift. - **Gates refuse what they cannot verify.** `catalog_diff`, `variant_reduce`, `ground_truth`, `coverage_gate`, `registry_enumerator` and `generate.py` use exit 0 for pass, 1 for a refusal and 2 for unusable input (`variant_reduce` adds 3 for an incomplete sweep). Malformed input, duplicate keys and unmapped spellings exit 2 instead of passing or tracebacking. - **gfx950 LDS gate in Python.** `supports_attention_dense` rejects tiles over the 160 KiB LDS budget, ported from `Gfx950AttentionDenseGeometry.hpp`; a census test checks that every shipped kernel's tile passes the engine's C++ check. - **`hkp_pack` pre-flight.** Every packed rocKE spec is checked by its builder's support predicate. A builder with no predicate, or a predicate that raises, fails the pack. - **Tests guard contracts, not rocKE internals.** Tests outside rocKE read the shipped catalogs or a synthetic registry instead of rocKE private names, C++ source text, or rocKE kernel counts and messages, so rocKE refactors do not break them. - **Spec-first tiled predicates** (gfx942, gfx950) so `hkp_pack` can validate tiled specs. ### Breaking changes (IngestorGenerator tooling; see its README) - `verify_variant_sets.py` and `coverage_gate.py` take `--manifest` instead of `--profile`; `HIPDNN_INGESTOR_PROFILE*` is renamed `HIPDNN_INGESTOR_MANIFEST*`. - `dispatch_parity.py`, `knob_sweep.py`, `reconcile_applicability.py` and `variant_reachability.py` are removed; the README's *Retired tools* table lists their replacements. - The engine manifest uses a new `enumerate:` schema, with `reduction:` and optional `ground_truth:` sections. Enum values in `enumerate.cells` must be member names. - Gates that passed silently now refuse: see the exit codes above. Ground-truth graph maps written before this change must be regenerated with `ground_truth.py graphs`. - `hkp_pack` fails the pack for a rocKE builder with no resolvable support predicate. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Yaswanth Raparti <yraparti@amd.com> Co-authored-by: BrianHarrisonAMD <169072757+BrianHarrisonAMD@users.noreply.github.com> Co-authored-by: Garby Gilbert <ggilbert@amd.com> Co-authored-by: Brian Harrison <brian.harrison@amd.com>
TheRock Submodule Bump ActivityNewest first
|
…-cache-locality Resolve the gfx950 dense conflicts with #13125: the gqa_pair checks and the persistent auto rule live in kernels/common here, so develop's right_bound exclusions move there; keep develop's empty-row guard before the epilogue decode. Re-bless the three persistent band goldens: two keep develop's machine code, the lookahead one gets the causal qb_major fold. #13024 makes the dispatcher registry the source of the gfx950 ingestor catalog. The C++ geometry launches only the qb_minor grid, so the manifest now pins the new opt-in candidate gfx950_dense_qbminor; the catalog is unchanged.
Port the #13125 gfx950 band to the gfx942 tiled bodies so they no longer serve only the bottom-right causal diagonal: - causal_top_left: context_len = 0 (top-left diagonal); ALiBi / qq-bias offsets follow it, as on gfx950. Mirrored in the C++ twins. - right_bound: 0 causal, R > 0 lookahead, -1 unbounded, applied at the per-score compares, the KV-loop prefix bound, the sliding-window range, valid_tail and the causal phase split. Python-only, as on gfx950; the pybind 2D/fastkv builders reject it instead of dropping it. - Name tokens tl / rbu / rb<R>; rejects right_bound with ALiBi / qq-bias. - The 4-warp GQA bodies take top-left but raise on right_bound != 0. - gfx950 C++ tiled 2D / fastkv / 3D entry points reject causal_top_left, which only their Python bodies implement. - New top-left parity configs (2D cfg7-9, 3D cfg5-6) gate both engines. Default-mask names and IR are unchanged. Not routed to yet: the host and dispatch still gate non-default masks off gfx942. Gate: gfx942_attention_tiled (2d, 2d_stress, 3d) and gfx950_attention_tiled (2d, fastkv_regp, 3d) GREEN at llvm20/llvm22/llvm23. Co-Authored-By: Claude <noreply@anthropic.com>
Mirror the #13125 gfx950 dense changes on gfx942, in both the default and persistent grids: right_bound (lookahead), non-causal left-only and two- sided windows, full attention including ragged cross-attention (seqlen_q != seqlen_kv), and a zero-output guard for rows with no visible key, emitted only when such rows can exist. Kernel names _full / _causal / _swa<W> / _rb<R> as on gfx950. A moving bottom-right diagonal, and a window or lookahead at bottom-right with seqlen_q != seqlen_kv, stay rejected with a reason. Default dense IR is unchanged (gfx942 dense golden test green). GPU (gfx942): test_attention_dense_gfx942_numeric 105 passed, including the band matrix through the spec, persistent and ragged cross-attention. Co-Authored-By: Claude <noreply@anthropic.com>
Closes the gfx942 known gap left by #13125: gfx942 now implements the same band as gfx950 (the kernels landed in the previous commits). - _has_no_mask_kernel covers gfx942: NO_MASK is full attention there (no longer the legacy causal body); non-causal bands are admitted instead of rejected. gfx1250 remains the known gap. - Host: gfx942 tiled 2D/3D accept non-default masks; the 4-warp GQA cohorts decline right_bound != 0 so those problems take the generic tiled body. The spec builder threads causal_top_left / right_bound into every gfx942 2D (bf16/fp16 flash, generic, 4-warp) and 3D spec. - dense_pipe serves the band; the gfx942 attention_dense candidate declares the dense band features. - gfx942 live benchmarks and attention_sweep pin BOTTOM_RIGHT_CAUSAL, which they relied on the NO_MASK default to mean. - Parity harness: band reference and --set topleft|nomask|band for gfx942; the dense prefill builder takes --right-bound. - Tests: gfx942 rows in test_unified_mask_wiring flipped to the gfx950 expectations plus band routing rows; new test_attention_unified_mask_gfx942_numeric.py. Docs updated. Dispatch suite: 359 passed. GPU (gfx942): unified mask numeric green, including the 4-warp empty-row and D256 rows. Co-Authored-By: Claude <noreply@anthropic.com>
…-key set Review follow-up from #13125, where the gfx950 dense kernel read the next batch's tokens for q-blocks past the keys. gfx942 is not affected: both grids enter the KV loop through a bounds-checked loop header, so such a block runs zero tiles (comment added at the start tile; IR unchanged). - Band rows (direct, D64, dispatched, sinks/LSE) run at batch=2 and require rows with no visible key to be exactly 0 in every batch. - TestDenseBandIndexTruthTable: q = 0, V[k] = e_k, so each output row is 1/n at exactly the visible keys; 6 bands x aligned / past-the-keys / ragged x grid and persistent. A deliberately injected over-read fails every -empty row and the past-the-keys truth-table rows, so the tests cover the #13125 bug. Co-Authored-By: Claude <noreply@anthropic.com>
…overread Review follow-ups from #13125, for gfx942: - TestBandIndexTruthTable (2D and 3D): the visible-key set equals the literal definition d - k < left and k <= d + right, for causal, windows, left-only, two-sided, lookahead and full, both alignments, including rows with no visible key. - TestDispatchedMixedCohort: request -> dispatch -> launch on [(512,512),(700,200),(200,700),(64,64)] for top-left causal, a top-left window and NO_MASK bands, fp16/bf16, tiled and auto; checks the spec carries the band and that the bottom-right body would not match. - TestBlockTableOverread: the 4-warp bodies stay in-bounds on a padded-free block table (child process, since a fault poisons the GPU context). Co-Authored-By: Claude <noreply@anthropic.com>
…overage Review follow-up on #13211: test_attention_unified_mask_gfx942_numeric.py joins the installed library GPU CTest list and its gfx950 twin from #13125 joins the attention GPU list next to gfx950 dense. The GPU attention coverage map gains explicit rows for both unified suites and for the gfx942 dense band additions (batch=2 band matrix, ragged cross-attention, empty rows, sinks/LSE band, truth table), updated counts, and the unequal-length gap row now lists the gfx942 cohorts. These suites are Torch-gated and skip in CI without Torch. Co-Authored-By: Claude <noreply@anthropic.com>
Port the #13125 gfx950 band to the gfx942 tiled bodies so they no longer serve only the bottom-right causal diagonal: - causal_top_left: context_len = 0 (top-left diagonal); ALiBi / qq-bias offsets follow it, as on gfx950. Mirrored in the C++ twins. - right_bound: 0 causal, R > 0 lookahead, -1 unbounded, applied at the per-score compares, the KV-loop prefix bound, the sliding-window range, valid_tail and the causal phase split. Python-only, as on gfx950; the pybind 2D/fastkv builders reject it instead of dropping it. - Name tokens tl / rbu / rb<R>; rejects right_bound with ALiBi / qq-bias. - The 4-warp GQA bodies take top-left but raise on right_bound != 0. - gfx950 C++ tiled 2D / fastkv / 3D entry points reject causal_top_left, which only their Python bodies implement. - New top-left parity configs (2D cfg7-9, 3D cfg5-6) gate both engines. Default-mask names and IR are unchanged. Not routed to yet: the host and dispatch still gate non-default masks off gfx942. Gate: gfx942_attention_tiled (2d, 2d_stress, 3d) and gfx950_attention_tiled (2d, fastkv_regp, 3d) GREEN at llvm20/llvm22/llvm23. Co-Authored-By: Claude <noreply@anthropic.com>
Mirror the #13125 gfx950 dense changes on gfx942, in both the default and persistent grids: right_bound (lookahead), non-causal left-only and two- sided windows, full attention including ragged cross-attention (seqlen_q != seqlen_kv), and a zero-output guard for rows with no visible key, emitted only when such rows can exist. Kernel names _full / _causal / _swa<W> / _rb<R> as on gfx950. A moving bottom-right diagonal, and a window or lookahead at bottom-right with seqlen_q != seqlen_kv, stay rejected with a reason. Default dense IR is unchanged (gfx942 dense golden test green). GPU (gfx942): test_attention_dense_gfx942_numeric 105 passed, including the band matrix through the spec, persistent and ragged cross-attention. Co-Authored-By: Claude <noreply@anthropic.com>
Closes the gfx942 known gap left by #13125: gfx942 now implements the same band as gfx950 (the kernels landed in the previous commits). - _has_no_mask_kernel covers gfx942: NO_MASK is full attention there (no longer the legacy causal body); non-causal bands are admitted instead of rejected. gfx1250 remains the known gap. - Host: gfx942 tiled 2D/3D accept non-default masks; the 4-warp GQA cohorts decline right_bound != 0 so those problems take the generic tiled body. The spec builder threads causal_top_left / right_bound into every gfx942 2D (bf16/fp16 flash, generic, 4-warp) and 3D spec. - dense_pipe serves the band; the gfx942 attention_dense candidate declares the dense band features. - gfx942 live benchmarks and attention_sweep pin BOTTOM_RIGHT_CAUSAL, which they relied on the NO_MASK default to mean. - Parity harness: band reference and --set topleft|nomask|band for gfx942; the dense prefill builder takes --right-bound. - Tests: gfx942 rows in test_unified_mask_wiring flipped to the gfx950 expectations plus band routing rows; new test_attention_unified_mask_gfx942_numeric.py. Docs updated. Dispatch suite: 359 passed. GPU (gfx942): unified mask numeric green, including the 4-warp empty-row and D256 rows. Co-Authored-By: Claude <noreply@anthropic.com>
…-key set Review follow-up from #13125, where the gfx950 dense kernel read the next batch's tokens for q-blocks past the keys. gfx942 is not affected: both grids enter the KV loop through a bounds-checked loop header, so such a block runs zero tiles (comment added at the start tile; IR unchanged). - Band rows (direct, D64, dispatched, sinks/LSE) run at batch=2 and require rows with no visible key to be exactly 0 in every batch. - TestDenseBandIndexTruthTable: q = 0, V[k] = e_k, so each output row is 1/n at exactly the visible keys; 6 bands x aligned / past-the-keys / ragged x grid and persistent. A deliberately injected over-read fails every -empty row and the past-the-keys truth-table rows, so the tests cover the #13125 bug. Co-Authored-By: Claude <noreply@anthropic.com>
…overread Review follow-ups from #13125, for gfx942: - TestBandIndexTruthTable (2D and 3D): the visible-key set equals the literal definition d - k < left and k <= d + right, for causal, windows, left-only, two-sided, lookahead and full, both alignments, including rows with no visible key. - TestDispatchedMixedCohort: request -> dispatch -> launch on [(512,512),(700,200),(200,700),(64,64)] for top-left causal, a top-left window and NO_MASK bands, fp16/bf16, tiled and auto; checks the spec carries the band and that the bottom-right body would not match. - TestBlockTableOverread: the 4-warp bodies stay in-bounds on a padded-free block table (child process, since a fault poisons the GPU context). Co-Authored-By: Claude <noreply@anthropic.com>
…overage Review follow-up on #13211: test_attention_unified_mask_gfx942_numeric.py joins the installed library GPU CTest list and its gfx950 twin from #13125 joins the attention GPU list next to gfx950 dense. The GPU attention coverage map gains explicit rows for both unified suites and for the gfx942 dense band additions (batch=2 band matrix, ragged cross-attention, empty rows, sinks/LSE band, truth table), updated counts, and the unequal-length gap row now lists the gfx942 cohorts. These suites are Torch-gated and skip in CI without Torch. Co-Authored-By: Claude <noreply@anthropic.com>
Port the #13125 gfx950 band to the gfx942 tiled bodies so they no longer serve only the bottom-right causal diagonal: - causal_top_left: context_len = 0 (top-left diagonal); ALiBi / qq-bias offsets follow it, as on gfx950. Mirrored in the C++ twins. - right_bound: 0 causal, R > 0 lookahead, -1 unbounded, applied at the per-score compares, the KV-loop prefix bound, the sliding-window range, valid_tail and the causal phase split. Python-only, as on gfx950; the pybind 2D/fastkv builders reject it instead of dropping it. - Name tokens tl / rbu / rb<R>; rejects right_bound with ALiBi / qq-bias. - The 4-warp GQA bodies take top-left but raise on right_bound != 0. - gfx950 C++ tiled 2D / fastkv / 3D entry points reject causal_top_left, which only their Python bodies implement. - New top-left parity configs (2D cfg11-13, 3D cfg18) gate both engines. - test_unified_lse_dispatch: re-pin gfx942's pre-LSE split-KV identity; its config_key / spec_hash move with the band fields the tiled specs gain. Default-mask names and IR are unchanged. Not routed to yet: the host and dispatch still gate non-default masks off gfx942. Gate: gfx942_attention_tiled (2d, 2d_stress, 3d) and gfx950_attention_tiled (2d, fastkv_regp, 3d) GREEN at llvm20/llvm22/llvm23. Co-Authored-By: Claude <noreply@anthropic.com>
Mirror the #13125 gfx950 dense changes on gfx942, in both the default and persistent grids: right_bound (lookahead), non-causal left-only and two- sided windows, full attention including ragged cross-attention (seqlen_q != seqlen_kv), and a zero-output guard for rows with no visible key, emitted only when such rows can exist. Kernel names _full / _causal / _swa<W> / _rb<R> as on gfx950. A moving bottom-right diagonal, and a window or lookahead at bottom-right with seqlen_q != seqlen_kv, stay rejected with a reason. Default dense IR is unchanged (gfx942 dense golden test green). GPU (gfx942): test_attention_dense_gfx942_numeric 105 passed, including the band matrix through the spec, persistent and ragged cross-attention. Co-Authored-By: Claude <noreply@anthropic.com>
Closes the gfx942 known gap left by #13125: gfx942 now implements the same band as gfx950 (the kernels landed in the previous commits). - _has_no_mask_kernel covers gfx942: NO_MASK is full attention there (no longer the legacy causal body); non-causal bands are admitted instead of rejected. gfx1250 remains the known gap. - Host: gfx942 tiled 2D/3D accept non-default masks; the 4-warp GQA cohorts decline right_bound != 0 so those problems take the generic tiled body. The spec builder threads causal_top_left / right_bound into every gfx942 2D (bf16/fp16 flash, generic, 4-warp) and 3D spec. - dense_pipe serves the band; the gfx942 attention_dense candidate declares the dense band features. - gfx942 live benchmarks and attention_sweep pin BOTTOM_RIGHT_CAUSAL, which they relied on the NO_MASK default to mean. - Parity harness: band reference and --set topleft|nomask|band for gfx942; the dense prefill builder takes --right-bound. - Tests: gfx942 rows in test_unified_mask_wiring flipped to the gfx950 expectations plus band routing rows; new test_attention_unified_mask_gfx942_numeric.py. Docs updated. Dispatch suite: 359 passed. GPU (gfx942): unified mask numeric green, including the 4-warp empty-row and D256 rows. Co-Authored-By: Claude <noreply@anthropic.com>
…-key set Review follow-up from #13125, where the gfx950 dense kernel read the next batch's tokens for q-blocks past the keys. gfx942 is not affected: both grids enter the KV loop through a bounds-checked loop header, so such a block runs zero tiles (comment added at the start tile; IR unchanged). - Band rows (direct, D64, dispatched, sinks/LSE) run at batch=2 and require rows with no visible key to be exactly 0 in every batch. - TestDenseBandIndexTruthTable: q = 0, V[k] = e_k, so each output row is 1/n at exactly the visible keys; 6 bands x aligned / past-the-keys / ragged x grid and persistent. A deliberately injected over-read fails every -empty row and the past-the-keys truth-table rows, so the tests cover the #13125 bug. Co-Authored-By: Claude <noreply@anthropic.com>
…overread Review follow-ups from #13125, for gfx942: - TestBandIndexTruthTable (2D and 3D): the visible-key set equals the literal definition d - k < left and k <= d + right, for causal, windows, left-only, two-sided, lookahead and full, both alignments, including rows with no visible key. - TestDispatchedMixedCohort: request -> dispatch -> launch on [(512,512),(700,200),(200,700),(64,64)] for top-left causal, a top-left window and NO_MASK bands, fp16/bf16, tiled and auto; checks the spec carries the band and that the bottom-right body would not match. - TestBlockTableOverread: the 4-warp bodies stay in-bounds on a padded-free block table (child process, since a fault poisons the GPU context). Co-Authored-By: Claude <noreply@anthropic.com>
…overage Review follow-up on #13211: test_attention_unified_mask_gfx942_numeric.py joins the installed library GPU CTest list and its gfx950 twin from #13125 joins the attention GPU list next to gfx950 dense. The GPU attention coverage map gains explicit rows for both unified suites and for the gfx942 dense band additions (batch=2 band matrix, ragged cross-attention, empty rows, sinks/LSE band, truth table), updated counts, and the unequal-length gap row now lists the gfx942 cohorts. These suites are Torch-gated and skip in CI without Torch. Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Closes the gfx950 forward-attention top-left causal gap in rocKE: the unified kernels silently served top-left as bottom-right (and were unconditionally causal), their dispatch candidates over-claimed a mask they did not implement, and dense mishandled cross-length / ragged shapes. The mask is now the cuDNN/hipDNN band (left =
sliding_window, right =right_bound, alignment =diagonal_alignment) computed exactly or rejected with a reason. Part of epic AICK-2500.JIRA ID : AICK-2505
Risk Assessment
High risk. On gfx950 the default request mask (
NO_MASK) now means full attention in the unified family instead of being served by a causal kernel, andAttentionRequestgains fields, abandcapability feature and new rejections; the kernel changes are large. Default-off IR is pinned byte-identical by the existing platform representative golden (re-run after merging develop), and the new variants' lowered IR is pinned by 26 added cases in that golden. gfx950 hardware parity is green, but no gfx942 / gfx1250 hardware run has been done for the dispatch changes that apply to those arches, and the new bodies are not yet mirrored in the C++ engine (see Known gaps).ASIC Coverage
Kernel changes are gfx950-only, so gfx950 hardware must pass (done locally, see below). The dispatch-layer changes are arch-wide:
SLIDING_WINDOWordinal handling, the new request fields andbandfeature, and gating of the gfx942 dense-pipe and gfx942/gfx1250 tiled paths. gfx942 and gfx1250 keep their legacyNO_MASK(causal) body by design, and non-causal bands are rejected there. That behaviour is covered by CPU tests, but a gfx942 GPU-lane run is required before merge to confirm no routing regression.Testing Summary
llvm20,llvm22andllvm23via the existing platform harness golden (rocke_representative_ir_sha256.json: 32attention_dense/gfx950and 10attention/gfx950cases). Scalar and tiled window / QQ-bias / D256 variants that golden does not cover were compared once against the base commit (31 cases x 3 flavors, 0 differences); no separate library golden is added.Testing Checklist
python library/tests/run_all.py- Status: Passed (2314 passed; 3 failures, all pre-existing and identical on clean develop:test_tiled_2d_shipped_geometries_compile_and_fit_budgetand the gfx942 densellvm23golden)python library/tests/run_all.py --gpu-only- ASICs: gfx950 - Status: Passed (536 passed, on the branch merged with develop)python platform/tests/rocke_installed_golden_test.py- Status: Passed (llvm20, llvm22, llvm23), re-run after merging develop (including the fp32 softmax-scale and dispatcher-restructure changes)git commit- Status: Passedpython library/tests/run_all.py --gpu-only- ASICs: gfx942 - Status: Not runTechnical Changes
Review follow-up: top-left is no longer folded into bottom-right on the unified family when the request's
seqlen_q == seqlen_k(batch maxima there; the kernels derive the diagonal per sequence); dense keeps that shortcut. Dense q-blocks entirely past the keys no longer read other batches' tokens (start tile clamped when rows can be empty; the dense band matrix now runs atbatch=2). The new variants' IR is pinned in the platform golden, and a GPU case covers request -> dispatch -> launch on a mixed-length cohort.Merged
develop(fix(rocke): Expose more knobs of SDPA kernels via updated dispatcher interface gfx942, gfx950 #12719 dispatcher restructure, fix(rocke): apply gfx950 dense softmax scale in fp32 #13122 fp32 softmax scale): the dense band moved intogfx950_dense.py(_dense_band,_is_ragged), the unified AttentionSpec fields intogfx950_unified.py, andright_boundis classified as a dense problem field. Under fix(rocke): apply gfx950 dense softmax scale in fp32 #13122's finite mask sentinel a row with no visible key is no longer NaN but averages V, so the dense kernels now zero such a row at the epilogue when its running max is still at the sentinel.Unified 2D tiled, 3D split-KV and scalar kernels: new
causal_top_leftandright_boundproblem/spec fields. The window anchor staysd - k < Wand the upper compare becomesk <= d + R(skipped when unbounded); tile bounds, the sliding-window tile end, the peel split and themask_limitthreshold all followR.R = 0lowers byte-identically.Dense kernel (default and persistent grids):
right_bound, non-causal windows, lookahead, ragged cross-attention, and a zero-output guard for rows with no visible key (previously stale data fromexp2(-inf - -inf)), emitted only when such rows can exist.Dispatch:
AttentionRequest.right_bound/diagonal_alignment, abandcapability feature,SLIDING_WINDOWread as the band trio (rejected when it names no bound), distinct kernel names (_tl,_rbu/_rb<R>,_sw<W>) and cache keys; unsupported combinations (e.g. ALiBi/QQ-bias with a right bound, dense bottom-right window atsq != sk) are rejected with a reason.Parity harness:
ref_paged_attnband reference and--set topleft|nomask|band; gfx950 benchmarks that relied on the default mask now pin bottom-right causal.Known gaps (follow-ups):
causal_top_left/right_boundbodies of the tiled 2D / 3D and unified (scalar) kernels are not yet mirrored inplatform/cpp/instances/, and there are nolibrary/tests/parity/*_emitpairs for them (e.g.attention_tiled_2d_ctx_prologue.cppstill hard-codescontext_len = seq_len - cur_batch_q_len). The default mask is unchanged, so Python/C++ byte-identity still holds; until the mirror lands the engines diverge on the new variants, whose Python IR is pinned only by the platform golden cases. Dense has no C++ mirror.q_len == kv_len. gfx942 / gfx1250 tiled kernels remain causal-only; dense window/lookahead at bottom-right alignment withsq != sk; pre-existing 2D tiled ALiBi + sliding-window NaN at bottom-right.🤖 Generated with Claude Code