Add native MLA QH64 fp8 persistent decode kernel for gfx942#3188
Conversation
Add native QH64 (gqa_ratio=64, qSeqLen=1) fp8 persistent decode
support for MI300X (gfx942), eliminating the need for the folded
QH16 path that reshapes 64 heads into 4x batch expansion.
Kernel binaries:
- mla_a8w8_qh64_qseqlen1_gqaratio64_v3_ps.co (decode, no LSE)
- mla_a8w8_qh64_qseqlen1_gqaratio64_lse_v3_ps.co (decode, with LSE)
Framework changes:
- mla.py: bypass fold path for gfx942 nhead=64 fp8 persistent
- attention.py: metadata tile size (ceil(64/128)=1 tile per batch)
- v1_2_device.cuh: mark gfx942 nhead=64 as natively_supported to
prevent batch expansion in metadata generator
- mla_asm.csv: register both kernel variants
- test_mla_persistent.py: enable gfx942 in nhead=64 test path
Tested on MI300X across batch={1,4,16,64,128} x ctx={1k,4k,8k,16k,32k}.
All 25 configurations pass correctness. Peak: 367 TFLOPS at b128/ctx32k.
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
|
|
Thank you for your hard works! I have one question. I met the cos_diff error when testing block_size 64. It's ok about block_size 1. Could you check precision for block_size 64? |
You are right, there is a switch to paged code path that was not correctly triggered. I'm working on the fix so far, thanks for testing! |
Updated mla_a8w8_qh64_qseqlen1_gqaratio64{_lse,}_v3_ps.co with corrected
output writeback that no longer overruns ptr_RP / ptr_LSEP per launch.
Raise kv_granularity floor to 32 for nhead=64 fp8/fp8 in the persistent
test so the metadata layer never emits sub-32-token partial works to this
kernel (it requires SUB_KV=32 partial granularity).
2d4d526 to
ab05216
Compare
…_gfx942 # Conflicts: # aiter/mla.py # aiter/ops/attention.py # csrc/kernels/mla/metadata/v1_2_device.cuh # op_tests/test_mla_persistent.py
ab05216 to
0363bea
Compare
|
@Byeong-Chan I have hopefully fixed the issues with paging and output writing, could you please test that if it's still relevant? |
|
@vstakhov-amd It has still precision issue in page_size 64. But if we removed 21 ctx length, then it's ok to precision. I think short length(<64) causes some issue. |
|
Is it the same or a different one? I have tested exactly the configuration you have mentioned with ctx_lens=1024, was it different this time? |
|
@Byeong-Chan it might be the case indeed that ctx_len < block_size is having an issue. We will have a look at that case. |
it's ok about context length 1024 and non-varlen. but, if we set short length(<64) or varlen, then it still has precision issue. varlen case: short length case: |
|
Also varlen has same issue. please, could you check this problem? |
It might be a common problem, but this specific kernel is qseqlen=1 only, there is no varlen. |
|
I mean qseqlen=1(decode_qlen), but kvlen(ctx_lens) is varlen in decode. |
|
I have fixed small context case but I have not tested |
|
But this is very important issue about batching variant context length when decoding phase real workload. ex) request1 - prefill done, 128 length kv cache and 1 token decode batching those two case -> precision issue |
Rebuild mla_a8w8_qh64_qseqlen1_gqaratio64{_lse,}_v3_ps.co with:
- Short paged-tail fix: route partial page64 tails (kv % SUB_KV != 0)
through masked tail processing using kv_last_page_lens. Without this
the kernel read garbage K/V for positions past the last valid token
and emitted NaN/Inf for short ctx_lens (e.g. kv=21 at batch=1).
- Phase B reframing for page > SUB_KV: avoid divide-by-zero in
int_div_ss by computing the loop count from full SUB_KV passes plus
a final partial pass length.
Validated on MI300X via op_tests/test_mla_persistent.py:
- kv=1024,batch=1,nhead=64,page=64,fp8: PASS (all references)
- kv=21,batch=1,nhead=64,page=64,fp8: PASS vs fp8 references,
bf16-golden delta within quantization noise floor (err=0).
Rebuild mla_a8w8_qh64_qseqlen1_gqaratio64{_lse,}_v3_ps.co to fix
per-batch kv length handling on the varlen decode path.
Before: at batch>=2 with varlen=True the kernel produced large
systematic errors (~33% of output elements deviated by >1, max delta
~1.6 vs fp8 reference) because per-batch kv_last_page_lens were not
applied per work item.
After, on MI300X via op_tests/test_mla_persistent.py:
kv=1024,batch=3,varlen=True,nhead=64,page=64,fp8:
fp8 golden vs aiter_asm: 28/98304 elems off, max delta 0.0146
fp8 split_out_ref: 28/98304 elems off, max delta 0.0146
Regression sweep (kv in {1024,21}, batch in {1,3}, varlen on/off):
no regression; all fp8 references pass or warn at quantization
noise level.
|
@Byeong-Chan I have hopefully fixed the both issues you have mentioned: ctx_lens < page_size and varlen support. Could you please give it another test iteration once you have time? Thanks in advance! |
|
@vstakhov-amd great! It's ok when page size 64 all test. thanks for your works! |
|
@ROCm/team_aiter could someone please review this change. This is a new gfx942 kernel to run GLM-4.5 in context split mode. |
# Conflicts: # csrc/kernels/mla/metadata/v1_2_device.cuh
Motivation
Jira link
Technical Details
Add native QH64 (gqa_ratio=64, qSeqLen=1) fp8 persistent decode support for MI300X (gfx942), eliminating the need for the folded QH16 path that reshapes 64 heads into 4x batch expansion.
Kernel binaries:
Framework changes:
Tested on MI300X across batch={1,4,16,64,128} x ctx={1k,4k,8k,16k,32k}. All 25 configurations pass correctness. Peak: 367 TFLOPS at b128/ctx32k.
Test Plan
Test Result
Submission Checklist