Repository navigation
Conversation
zcnrex
marked this pull request as ready for review
October 17, 2026 06:28
zcnrex
requested review from
BBuf,
DarkSharpness,
HaiShaw,
HydraQYH,
celve and
yuan-luo
as code owners
October 17, 2026 06:28
4 of 5 tasks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…RoPE on decode only Generalize the BF16 QK RMSNorm + MRoPE kernel into fused_qk_norm_rope_with_cache: 1D positions, no axis map. The rotation math follows the cos_sin_cache dtype, FP32 (plain RoPE, matches rope.cuh) or BF16 (MRoPE, matches triton_mrope_fused). Qwen3Attention now also uses it for plain RotaryEmbedding, so dense text Qwen3 benefits. MRoPE takes the fused path only in decode, where the three position rows are identical and positions[0] is exact. Add a bit-exact regression test against both split paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 of 4 tasks
Collaborator
Author
|
Superseded by #47993. It reuses #46908's Triton table kernel for Qwen3-VL decode MRoPE, and the output stays bit-identical to the split path. On B300 the separate CUDA kernel here was only 0.2-0.35 us/layer faster than the table route at decode batch <= 32. That's too small a gain to justify maintaining another CUDA kernel, and #46908 already covers the plain-RoPE half. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Qwen3 attention runs Q/K RMSNorm and RoPE as two separate kernels. This PR fuses them into one JIT kernel on datacenter Blackwell (SM100) for BF16 Q/K with 128-element heads, full-width NeoX rotation, and 1–128 tokens. That covers:
RotaryEmbedding), in decode and in short extends.MRotaryEmbedding), in decode only.Every other configuration keeps the existing split path.
Modifications
Kernel.
FusedQKNormRoPEWithCache<kUsePDL, CacheT>inelementwise/fused_qknorm_rope.cuhreuses the warp kernel fromqknorm.cuh(load, reduction, store) through an epilogue hook, and applies RoPE from the model'scos_sin_cachebefore the store. The rotation arithmetic follows the cache dtype, so each path matches its split counterpart:rope.cuh, whichapply_rope_with_cos_sin_cache_inplaceuses.triton_mrope_fused.It accepts strided Q/K (views into packed QKV) and 1D int64 positions, and schedules one warp per head. Ordinary QK normalization keeps its persistent scheduling, and the head_dim-128 half-warp kernel from #45214 is unaffected.
API.
fused_qk_norm_rope_with_cache(q, k, q_weight, k_weight, cos_sin_cache, positions, eps)insglang.kernels.ops.attention.fused_qknorm_rope, registered asattention.fused_qk_norm_rope_with_cache.Qwen3 dispatch (
models/qwen3.py):head_dim == rotary_dim == 128, NeoX style, a rotary embedding of exactlyRotaryEmbeddingorMRotaryEmbeddingwithmrope_section, no forced-native rotary, no deterministic inference, and no Inductor prefill.ForwardBatch._compute_mrope_positions_decode), sopositions[0]is exact. MRoPE extend and speculative steps keep the Triton path.forward_prepare_nativenow takesforward_batchso it can read the forward mode.Out of scope: KV-cache write fusion, QKV projection fusion, and MoE Qwen3 (
qwen3_moe.py).Merged with upstream main at
cb55d77d37.Validation
On commit
9e62fc7a69, one NVIDIA B300 (SM 10.3). Another job was running on that GPU, so these are correctness results only.24/24 cases match the split path bit for bit. The new test is
test/registered/kernels/ops/attention/test_fused_qk_norm_rope_with_cache.py, and it compares against:apply_rope_with_cos_sin_cache_inplace.triton_mrope_fusedwith three identical position rows.Coverage: 1, 17 and 128 tokens; Q/K heads 8/2 and 32/8; packed QKV with and without 64 elements of row padding. V and padding are byte-identical to the split path.
Sanity check: the kernel changes about 99.9% of Q/K values, leaves V untouched, and its output depends on position.
The earlier results on
70b63a4575(the MRoPE-only version on GB300) predate both this generalization and the merge of #45214, and have not been rerun. They covered 168 synthetic MRoPE cases, 27 CUDA-graph replays, 60 base-vs-PR QK-norm comparisons, and the 560 existingtest_qknorm.pycases.Kernel Performance (stale, rerun pending)
Kernel-only latency in microseconds, median of three CUDA-graph runs (MRoPE, BF16, head_dim 128, GB300):
Validation Limits
These are kernel-level correctness results only. No end-to-end accuracy, serving-throughput, or decode-latency measurements have been made, and no serving improvement is claimed yet.
Checklist
🤖 Generated with Claude Code
CI States
Latest PR Test (Base): ❌ Run #40563264384
Latest PR Test (Extra): ❌ Run #40563263945
Latest PR Test (AMD ROCm 10): ❌ Run #40563264343