Skip to content

perf(rocke): enable exp2_fast for bf16 head_dim=128 in gfx942 dense prefill - #10885

Merged
AviralGoelAMD merged 4 commits into
developfrom
users/avirgoel/rocke/gfx942-dense-bf16-exp2
Aug 19, 2026
Merged

AviralGoelAMD merged 4 commits into
developfrom
users/avirgoel/rocke/gfx942-dense-bf16-exp2

Conversation

@AviralGoelAMD

Copy link
Copy Markdown
Contributor

ISSUE ID : AICK-1991

Enable exp2_fast for bf16 head_dim=128 in the dense prefill softmax — the last config still on the slower guarded exp2 (fp16 and bf16-D64 already used it).

The holdout was a stale spill: it was measured on the old pre-lazy-rescale body. The current kernel doesn't spill with exp2_fast (zero scratch on both grids), and the output is bit-identical to plain exp2 (both softmax args are ≤ 0, exactly its precondition) — so it's a free softmax speedup on bf16-D128.

Diff: _use_exp2_fast → True, plus a golden re-bless of the four bf16-D128 IR cases (fp16 and D64 unchanged; gfx950 untouched). No C++ mirror under library/kernels/, so byte-identity doesn't apply.

…refill

The bf16-D128 exp2_fast holdout was justified by a pre-lazy-rescale spill over the
waves-per-eu=2 cap. rocprofv3 on the current lazy-rescale kernel shows the opposite:
VGPR drops and scratch stays zero, output numerically identical to plain exp2. Remove
the stale holdout in _use_exp2_fast (return True), update the in-file status/policy
comments that referenced the old exception, and re-bless the four bf16-D128 golden
cases across both llvm flavors; fp16 and D64 are byte-identical.
@AviralGoelAMD
AviralGoelAMD force-pushed the users/avirgoel/rocke/gfx942-dense-bf16-exp2 branch from d4de8c1 to 5da51c8 Compare August 17, 2026 19:01
@therock-pr-bot

therock-pr-bot Bot commented Aug 17, 2026 •

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ✅ Pass —
🔎 pre-commit ✅ Pass —
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —
🤖 therock-pr-bot ✅ Pass —

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables exp2_fast for gfx942 bf16 D128 dense-prefill kernels and updates their golden IR hashes.

Changes:

  • Enables exp2_fast for all gfx942 configurations.
  • Documents updated spill measurements.
  • Re-blesses affected LLVM 20/22 golden outputs.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
library/kernels/gfx942/attention_dense.py Enables the optimized exponential path.
library/tests/golden/attention_dense_gfx942_ir_sha256.json Updates affected IR sizes and hashes.
Suppressed comments (1)

dnn-providers/hip-kernel-provider/rocke/library/kernels/gfx942/attention_dense.py:538

  • This policy change leaves the existing spill-matrix test failing deterministically: test_exp2_fast_gate_matches_the_spill_measured_matrix still parameterizes (128, "bf16", False) and asserts the result at tests/test_attention_dense_gfx942.py:846-865. Update that case to expect True and revise its stale spill rationale so the dense gfx942 test lane passes.
    return True

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@AviralGoelAMD
AviralGoelAMD requested a review from a team August 18, 2026 04:02

@aosewski aosewski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went through this one carefully, including re-running the golden fixture at both flavors and re-measuring the registers with the prefill occupancy probe compiled for gfx942 (ROCm 7.1 / llvm20).

The change itself checks out. The IR delta is exactly the intrinsic swap and nothing else (34 llvm.exp2.f32 -> llvm.amdgcn.exp2.f32, byte-identical otherwise at both llvm20 and llvm22), the golden re-bless is accurate and minimal, and the resource claim holds: bf16-D128 goes 196 -> 174 VGPR / 0 spill on the default grid and 200 -> 180 / 0 spill on the persistent one. bf16-D64 even loses a 12-VGPR spill. No objection to the flip.

Comments below are all prose and test hygiene. The recurring one is that the doc-consistency pass caught the two big docstrings but left about five other places still describing the holdout you just removed.

- Add default-grid numeric coverage and a forced-off/on A/B (torch.equal) that
  actually distinguishes the two exp2 arms on both bf16-D128 grids; the fp32-SDPA
  oracle (tol=4e-2) cannot.
- Parametrize the softmax-intrinsic test on the tuning, not the policy, so the
  plain-exp2 codegen arm stays pinned now that the policy is True everywhere; add
  the bf16-D128 row to the fused-rescale cast-count test.
- Rename the policy test to test_exp2_fast_is_enabled_for_every_config and
  de-spill its docstring/section header.
- Correct kernel + README prose: drop the unsupported "lazy-rescale schedule
  change" cause (the kernel body is unchanged since first commit), restore the
  tried/rejected/re-adopted lever-record entry, replace "VGPR-neutral" with the
  measured VGPR reduction, and use "numerically identical for every reachable
  softmax argument".
- Wrap over-length comment lines to the 88-col style limit.
@AviralGoelAMD
AviralGoelAMD requested review from a team and aosewski August 18, 2026 14:46

@aosewski aosewski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything from the last round is addressed — thanks for the thorough pass, particularly reframing the rationale instead of just softening the wording.

I re-verified rather than reading the diff: golden fixture green at both llvm20 and llvm22 (untouched, correctly — only prose and tests moved), CPU lane clean apart from the four pre-existing paged-field failures that also fail on the merge-base, and all three over-length lines are gone.

I paid particular attention to the new test_exp2_fast_matches_plain_exp2, since it's skip-gated and CI can't catch a mistake in it. It holds up: the signatures line up (_spec(..., *, batch, sq) and run_attention_dense_torch(*, spec, q, k, v, out, scale, tuning)), both rows collect, and the premise it rests on is real — forced-off and forced-on genuinely produce two different binaries on both grids:

bf16 D128 default   off -> ..._wpe2_e2f0   fast= 0 plain=33
                    on  -> ..._wpe2        fast=33 plain= 0
bf16 D128 persist   off -> ..._wpe2_e2f0   fast= 0 plain=33
                    on  -> ..._wpe2        fast=33 plain= 0

That's the gate the "results unchanged" claim was missing, and it's a better answer than the cohort row I asked for.

Approving. Two leftovers below — neither blocks this, but flagging them so they don't quietly become permanent.

The exp2_fast review pass renamed the test section header to "fused rescale"
but left three sibling mentions still reading "fused/lazy rescale". On gfx942
the only "lazy" artifact is an inert kernel-name token, so the "/lazy" wording
misdescribes the mechanism (a single fused pass: exp2 -> l_local accumulate ->
cast -> pack). Align all three to "fused rescale" -- the P2 progress-table
header and the rescale comment in attention_dense.py, and the fused-rescale
test docstring -- so the file names the mechanism one way. Comment/docstring
only; no code, IR, or golden change.
@AviralGoelAMD
AviralGoelAMD enabled auto-merge (squash) August 19, 2026 13:33
@AviralGoelAMD
AviralGoelAMD merged commit 4ca6925 into develop Aug 19, 2026
77 of 80 checks passed
@AviralGoelAMD
AviralGoelAMD deleted the users/avirgoel/rocke/gfx942-dense-bf16-exp2 branch August 19, 2026 15:14
AviralGoelAMD added a commit that referenced this pull request Aug 25, 2026
…2 dense prefill) (#11079)

**Hot fix** for a short-sequence regression from #10885 (AICK-1991),
which enabled `exp2_fast` for bf16 `head_dim=128` unconditionally. On
the develop merge base (gfx942, ROCm 7.2.2, same-node A/B) it clearly
regresses short-seq dense prefill (~-15 to -21% at Sq <= 1024) while
winning at Sq >= 4096 (+8-10%); Sq 2048 sits in the same-node run-to-run
noise band.

Guard: bf16 `head_dim=128` uses `exp2_fast` only when `seqlen >= 4096`;
shorter sequences revert to plain `exp2` (their original, pre-#10885
perf). The conservative cut never regresses a shape (it forgoes at most
a noise-level Sq 2048 win). fp16 and D64 are unaffected; gfx950 makes an
independent exp2_fast decision and is not covered here.

The proper fix is seqlen-aware kernel selection in the rocKE dispatcher;
that work is WIP, so this lands the guard in the kernel builder as a hot
fix.

Jira: AICK-1991
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants