[TRITON][GLUON] Prefill MQA Logits kernel tuning for GLM 5.x - #4563
Merged
Merged
Conversation
Contributor
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
|
vgokhale
reviewed
Aug 4, 2026
vgokhale
approved these changes
Aug 4, 2026
1 task
This was referenced Aug 8, 2026
Ishiki-Iroha
added a commit
to Ishiki-Iroha/aiter
that referenced
this pull request
Aug 21, 2026
xiaobochen-amd
pushed a commit
to xiaobochen-amd/aiter
that referenced
this pull request
Aug 28, 2026
… offset, not tensor bytes (#4) * [TRITON][GLUON] Prefill MQA Logits kernel tuning for GLM 5.x (ROCm#4563) (cherry picked from commit aded0f8) Also carries the two-line `block_m = 1` for the non-gfx950 branch from ROCm#4246. This commit routes the launch grid through block_m but only defines it under `arch == "gfx950"`, so without those lines every other arch raises NameError at the kernel launch. Upstream ran with that hole from ROCm#4563 until ROCm#4246. * [Bugfix][Triton][gfx950] fp8_mqa_logits: gate buffer ops on the int32 offset, not tensor bytes Prefill shapes whose fp32 logits pass 2 GiB abort the AMDGCN backend at JIT time (Sequence.h:275 "Begin must be less or equal to End"). BLOCK_M=2 is selected for seq_len > 4096 but only compiles with buffer stores, and the buffer-store gate switches off at 2 GiB, so the two combine into a hard crash. For GLM-5.x that is any chunked prefill of 8192 tokens against a context past 65,536. The gate had the wrong unit. Buffer ops address through a 32-bit offset, but the kernel re-bases the pointer per row and per KV tile before each access, so that offset never has to span the tensor. What must fit in int32 is the largest element offset the kernel forms, because the row strides stay 32-bit on the buffer path and are only widened to int64 on the fallback path. Counting bytes rather than elements made the limit 4x too tight for an fp32 output. Measured on MI355X, 32 heads x 128 head_dim, against the plain-store path. Output is bit-identical in every case (max rel err 0.00e+00): s_q s_k logits plain store buffer store speedup 8192 65536 2.00 GiB 3.557 ms 2.941 ms 1.21x 8192 95457 2.91 GiB 6.105 ms 4.577 ms 1.33x 8192 131072 4.00 GiB 9.812 ms 6.489 ms 1.51x 16384 131072 8.00 GiB 21.738 ms 12.879 ms 1.69x 8192 262144 8.00 GiB 25.710 ms 14.184 ms 1.81x The new boundary is exact rather than approximate: 8192x262144 and 16384x131072 both place the largest offset at exactly INT32_MAX and are bit-correct, while 16384x139264 (1.06 x 2^31) and 32768x131072 (2^32) fault. End to end, a 21-layer GLM-5.x indexer prefill of 9,695 new tokens against a 96,960-token context at chunk 8192 drops from 150.2 ms to 118.4 ms. The existing cases top out at s_q=1024, s_k=1560, four orders of magnitude below the gate, which is why nothing caught this. Added 8192x65664 and 8192x98304, which crash the process on current main. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Mehmet Cagri <mehmet.kaymak@amd.com> Co-authored-by: Jiejing Zhang <jiejizha@smci355-ccs-aus-n02-29.prov.aus.ccs.cpe.ice.amd.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 task
JohnQinAMD
pushed a commit
to xiaobochen-amd/aiter
that referenced
this pull request
Aug 28, 2026
… offset, not tensor bytes (#4) * [TRITON][GLUON] Prefill MQA Logits kernel tuning for GLM 5.x (ROCm#4563) (cherry picked from commit aded0f8) Also carries the two-line `block_m = 1` for the non-gfx950 branch from ROCm#4246. This commit routes the launch grid through block_m but only defines it under `arch == "gfx950"`, so without those lines every other arch raises NameError at the kernel launch. Upstream ran with that hole from ROCm#4563 until ROCm#4246. * [Bugfix][Triton][gfx950] fp8_mqa_logits: gate buffer ops on the int32 offset, not tensor bytes Prefill shapes whose fp32 logits pass 2 GiB abort the AMDGCN backend at JIT time (Sequence.h:275 "Begin must be less or equal to End"). BLOCK_M=2 is selected for seq_len > 4096 but only compiles with buffer stores, and the buffer-store gate switches off at 2 GiB, so the two combine into a hard crash. For GLM-5.x that is any chunked prefill of 8192 tokens against a context past 65,536. The gate had the wrong unit. Buffer ops address through a 32-bit offset, but the kernel re-bases the pointer per row and per KV tile before each access, so that offset never has to span the tensor. What must fit in int32 is the largest element offset the kernel forms, because the row strides stay 32-bit on the buffer path and are only widened to int64 on the fallback path. Counting bytes rather than elements made the limit 4x too tight for an fp32 output. Measured on MI355X, 32 heads x 128 head_dim, against the plain-store path. Output is bit-identical in every case (max rel err 0.00e+00): s_q s_k logits plain store buffer store speedup 8192 65536 2.00 GiB 3.557 ms 2.941 ms 1.21x 8192 95457 2.91 GiB 6.105 ms 4.577 ms 1.33x 8192 131072 4.00 GiB 9.812 ms 6.489 ms 1.51x 16384 131072 8.00 GiB 21.738 ms 12.879 ms 1.69x 8192 262144 8.00 GiB 25.710 ms 14.184 ms 1.81x The new boundary is exact rather than approximate: 8192x262144 and 16384x131072 both place the largest offset at exactly INT32_MAX and are bit-correct, while 16384x139264 (1.06 x 2^31) and 32768x131072 (2^32) fault. End to end, a 21-layer GLM-5.x indexer prefill of 9,695 new tokens against a 96,960-token context at chunk 8192 drops from 150.2 ms to 118.4 ms. The existing cases top out at s_q=1024, s_k=1560, four orders of magnitude below the gate, which is why nothing caught this. Added 8192x65664 and 8192x98304, which crash the process on current main. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Mehmet Cagri <mehmet.kaymak@amd.com> Co-authored-by: Jiejing Zhang <jiejizha@smci355-ccs-aus-n02-29.prov.aus.ccs.cpe.ice.amd.com> Co-authored-by: Cursor <cursoragent@cursor.com>
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
GLM 5 series use number of q-heads = 32, but this kernel was originally tuned for 64 heads.
This PR improves performance for GLM 5 via kernel updates + tuning.
Technical Details
Now the kernel supports handling 2 tokens together to increase the work per WG (since 32*2=64). While there is still some performance gap between GLM 5 config and dsv4 one, this PR closes that gap quite a bit.
Test Plan
Existing tests are extended to include GLM 5 case as well.
Test Result
Tests pass.
Performance
While DSV4 config (num_heads=64) shows some regression when # tokens~= 4k, specifically 1k/1k case, those cases appear rarely during inference as batching typically goes for >= 8k tokens.
Results are from MI355.
Baseline and new column format:
{time} us / TFLOPsnum_heads = 32
num_heads = 64