Repository navigation
[HIP] [JIT] Add gfx950 prefill FP8 MQA logits - #7183
sumin-hong wants to merge 1 commit into
Conversation
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
One backend per PR: PR title tags & labels: |
NOT READY FOR HUMAN REVIEWPR Self-ReviewRevision Author self-review accepted. Readiness report: Author answers
Show the author's self-review answersBehavior and intentValidation and unverified scopePR-specific questionChanged op testsPR state
Copilot findings
Code and op-test hygiene
Required CI
Shadow mode reports what would block but keeps the status successful. Set |
Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Sumin Hong <sumin.hong@moreh.io>
4403a8a to
460c230
Compare
[HIP] [JIT] fp8_mqa_logits: v35w gfx950 prefill indexer logits kernel
Motivation
This PR adds a faster HIP kernel for the prefill fp8 MQA indexer logits used by GLM-5.x / DeepSeek-V3.2 sparse attention, on gfx950 (MI355X):
The added API and JIT module are:
aiter.ops.fp8_mqa_logits.fp8_mqa_logits/is_supportedmodule_fp8_mqa_logitsIt is an alternative to the Triton/Gluon
aiter.ops.triton.attention.fp8_mqa_logits. It supports n_heads = 32 and head_dim = 128 only; other shapes are routed viais_supported().Design (
csrc/kernels/fp8_mqa_logits.cu)vmcntwaits are placed by hand, becausevmcntalso counts the logits stores and compiler-derived waits drain them every stage.v_mfma_f32_32x32x64_f8f6f4. The fp32 epilogue is scalar (v_maxrelu,v_fmawith w) and is interleaved under the MFMAs. On gfx950, scalar VALU co-issues with an independent MFMA, but packedv_pk_*does not. Accumulation uses even/odd chains in a fixed order.v_permlane32_swaphead reduction is inline asm, because the clang builtin miscompiles its 2nd result on ROCm 7.2.3. kv_scale is applied after the reduction. The tail of each row pair is deferred by one sub-tile so it fills the MFMA→VALU hazard window, which leaves nos_nopin the loop.grid.y = SplitN. Withclean_logitsthe kernel writes -inf itself, so there is notorch.fullpass.(SplitN, reverse_rows)comes from a makespan model fitted on MI355X.-fno-honor-nans -fno-slp-vectorize -mllvm -disable-machine-sink:-fno-slp-vectorize: otherwise the epilogue is re-packed intov_pk_fma.-mllvm -disable-machine-sink: otherwise the last row's MFMA pair sinks past the loop exit.Kernel time on the GLM-5.3-Flash table shapes (MI355X, µs, clean_logits=True)
Setup:
vllm/vllm-openai-rocm:v0.30.0.Geomean vs FlyDSL #4538: 1.32× with clean_logits=True and 1.39× with clean_logits=False. It is also faster than every stronger baseline we measured, per shape:
3.7.0+amd.rocm7.2.0.git89002410)Against the best of those on each shape, the geomean is 1.26× (clean) and 1.30× (no-clean). The one exception is 8192×8192 multi_req, where this PR loses by 3% (clean) and 18% (no-clean, vs Gluon on the AMD Triton).
Test plan
python3 op_tests/test_fp8_mqa_logits.py --num-heads 32 --head-dim 128: all 150 HIP cases pass. They cover 6 window modes (causal, cp, misaligned, empty, past_end, multi_req), clean_logits 0/1, and a NaN-poisoned output buffer. The -inf mask matches exactly andcheckAllcloseerr = 0.Known limitations
SplitN=20. Callers that know the layout can passSplitN; a layout-aware heuristic is a follow-up.is_supported()plus a size gate in the caller if needed.emptyandpast_endop-test modes).Related work
Current validation
AI assistance: Claude Code was used in the source development; OpenAI Codex was used for the rebase, static validation, and preparation of this PR.
PR Self-Review
Reviewed revision
460c230bae21403b6e1a2a48e3525a3003343249Behavior and intent
This adds an opt-in gfx950 HIP prefill MQA logits operator. It computes weighted ReLU dot products over a contiguous gathered K buffer and supports clean or caller-managed output masks; existing Triton/Gluon and FlyDSL paths remain available. The aim is improved performance for the supported GLM indexer shapes.
Validation and unverified scope
On the rebased head, Python source AST and JIT configuration were compared to the source, the HIP kernel was checked against the prior PR head, and Black 26.3.0, Ruff 0.16.0, Python syntax and git diff --check passed. The supplied MI355X/ROCm measurements and commands are detailed above and predate this rebase. Unverified: GPU correctness, benchmarks and model evaluation have not been run on the current head; remote CI awaits maintainer approval.
PR-specific question
The intended contract is gfx950, 32 heads, head dimension 128, FP8 Q/K, float32 scales and weights, and int32 row bounds. The caller must check is_supported and supply the documented dtypes and contiguous layouts; the operator does not automatically route unsupported inputs. The C++ entry checks shape, contiguity and one-byte Q/K storage, but one-byte storage alone does not prove the FP8 dtype.
Changed op tests
op_tests/test_fp8_mqa_logits.py compares the new operator and Triton to the reference with clean and unclean outputs, poisoned buffers, causal, CP, misaligned, empty, past-end and multi-request windows. This new HIP entry and its masking behavior are not covered by the existing backend-only tests.