Conversation
The fused RoPE kernel used a single head_stride_bytes for both q and k, derived from q's head dimension stride. For MLA models like GLM5 where q and k have different head dims (q: [N, 64, 64] stride 256 vs k: [N, 1, 64] stride 64), this caused illegal memory access when indexing into k with q's stride. Split head_stride_bytes into q_head_stride_bytes and k_head_stride_bytes in FusedRopeParams. The kernel now selects the correct stride based on whether it's processing a q or k head. The pre-offset trick for k_ptr is updated to use k's head stride. Fixes sgl-project#20559
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request resolves a critical illegal memory access bug in the fused RoPE kernel that occurred in MLA models with asymmetric query and key head dimensions. The fix involves refactoring the kernel to use separate head stride parameters for query and key, ensuring correct memory access and improving the stability and compatibility of the RoPE implementation across diverse model architectures. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request addresses a critical illegal memory access bug in the RoPE kernel for MLA models. The root cause was the use of a single head stride for both Q and K tensors, which can have different head dimensions in MLA models. The fix correctly introduces separate q_head_stride_bytes and k_head_stride_bytes and applies them consistently throughout the non-fused and fused RoPE kernels, including pointer offsets and cache access. The changes are logical and effectively resolve the reported issue. I have one minor suggestion to improve code consistency.
| .base_params = params, | ||
| .v_ptr = v.data_ptr(), | ||
| .k_cache = pointer::offset(k_cache.data_ptr(), -k_offset), | ||
| .k_cache = pointer::offset(k_cache.data_ptr(), -static_cast<int64_t>(num_qo_heads) * k_head_stride_bytes), |
There was a problem hiding this comment.
For consistency and to avoid code duplication, it's better to reuse the k_offset variable, which is calculated just a few lines above with the correct k_head_stride_bytes. This also makes the intent clearer, as both k_ptr and k_cache are offset by the same amount for the same reason.
.k_cache = pointer::offset(k_cache.data_ptr(), -k_offset),
|
hi. my question is:
|
|
Thanks @DarkSharpness — you're right that with I don't have access to the GLM5 model or the specific hardware to reproduce the IMA. My analysis was based on the stride values in the issue ( Given your comment on #20559 that you plan to write a new kernel with broader stride support, should I close this PR? The split-stride change is still correct in principle (handles the general case where |
Could you please post full benchmark result of this PR? As long as there is no performance drawback, we can simply adopt this PR. Thanks a lot. We did not support different stride because for q k because typically they should be contiguous in num head dimension. |
|
Thanks! I don't have GPU access to run the benchmark locally. The change only adds one extra field to the params struct and a ternary select in the kernel ( If someone with GPU access could run |
I can run the benchmark for you some time later. I also expect there should be no much overhead. |
|
Closing this — the IMA root cause has been identified by @xu-yfei in #20559 as a kvcache index OOB in The stride separation change is still correct in principle but isn't solving the reported problem. Thanks @DarkSharpness for the review. |
Motivation
The fused RoPE kernel crashes with illegal memory access (IMA) on GLM5 FP8 because it uses a single
head_stride_bytes(derived from q) for both q and k heads. MLA models have different head dimensions for q and k:[8, 64, 64]→ head stride 256 elements[8, 1, 64]→ head stride 64 elementsUsing q's stride (256) to index into k's memory causes out-of-bounds access.
Fix
Split
head_stride_bytesintoq_head_stride_bytesandk_head_stride_bytesinFusedRopeParams. The kernel selects the correct stride based on whether it's processing a q or k head. The pre-offset trick fork_ptris updated to use k's head stride consistently.Both the non-fused (
fused_rope_kernel) and fused (fused_rope_store_kernel) paths are updated. The fused path'sRuntimeCheckis also split to validate both strides independently.Fixes #20559