Repository navigation
[MiniMax-M3.1] FP4 index-K cache: --index-cache-dtype fp4 (2/3) - #2745
Closed
zhuyuhua-v wants to merge 2 commits into
Closed
zhuyuhua-v wants to merge 2 commits into
zhuyuhua-v wants to merge 2 commits into
Conversation
Adds atom/model_ops/minimax_m3/sglang_nvfp4/, vendored from SGLang (Apache-2.0, python/sglang/kernels/ops/attention/minimax_sparse/, image lmsysorg/sglang@sha256:2d74f6ea...): the NVFP4 (MSA-v1) row loads with the gfx950 hardware e2m1 -> fp16 conversion, the Gluon sparse decode kernel over a packed NVFP4 K/V cache plus its top-k chunk merge, and the fused target-verify index score + top-k kernel. ATOM-side changes to the vendored code: - block-table addressing: the slot of logical block X is block_table[req, X] * 128, instead of SGLang's req_to_token rows; - block pointers removed (make_block_ptr is gone in Triton 3.8) and gl._reinterpret -> gl.reinterpret; - module-level constants are tl.constexpr. No callers yet; the FP4 index cache and the NVFP4 sparse KV pool use them in the follow-up commits.
Stores the M3 lightning-indexer keys as NVFP4: per key a D/2-byte e2m1 payload (two codes a byte, even element in the low nibble) and D/16 E4M3 block scales with a unit outer scale -- SGLang's M3 NVFP4 index pool format, 72 B per key instead of 128 B for FP8. - index_fp4.py: Triton store kernel (per 16 elements scale = e4m3(amax / 6), codes rounded half-to-even, saturating at 6) and a torch dequant reference. - Pool: two uint8 fields, index and index_scale, in the same entry as the KV; the binder hands each sparse layer its payload/scale views and a shared token-major BF16 staging buffer. - Write: aiter's fused qk-norm/rope/cache kernel only writes BF16/FP8 index keys, so it writes this step's keys into the staging buffer (identity slot mapping) and index_fp4_store quantizes them into the paged planes at the real slots. - Scorers: the prefill block scorer and the decode tiled scorer take the scale plane (IS_FP4) and decode rows with the gfx950 hardware e2m1 -> fp16 conversion, as separate even/odd fp16 tiles whose dots are chained, so no interleave shuffle is needed. - Indexer CP is refused with an FP4 index (its context scorer reads FP8/BF16 keys only). Top-k on random data matches the FP8/BF16 reference on 100% of rows for decode and prefill. KV block bytes for MiniMax-M3.1-Flash TP4 drop from 3,179,520 to 2,749,440 (-13.5%).
This was referenced Oct 27, 2026
MengqingCao
added a commit
that referenced
this pull request
Oct 27, 2026
MengqingCao
added a commit
that referenced
this pull request
Oct 28, 2026
zhuyuhua-v
force-pushed
the
yuhzhu/m31-sglang-nvfp4-kernels
branch
from
October 28, 2026 07:03
094f4e5 to
02ff29d
Compare
Collaborator
Author
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.
Summary
This PR adds
--index-cache-dtype fp4for MiniMax-M3: the lightning-indexer keys are stored as NVFP4. It is stacked on the vendored-kernels PR (#2744); review only the top commit.Per cached key (D = 128):
That is 72 B, against 128 B for FP8. It is the format SGLang's M3 NVFP4 index pool stores.
index_fp4.py): a Triton kernel quantizes per 16 elements withscale = e4m3(amax / 6)and codes rounded half-to-even, saturating at 6. A torch dequant reference sits beside it.indexandindex_scale, live in the same entry as the KV. Each sparse layer gets its payload and scale views plus a shared token-major BF16 staging buffer.index_fp4_storequantizes them into the paged planes at the real slots._index_block_score_kernel(prefill) and_decode_index_score_tiled_kernel(decode) take the scale plane (IS_FP4). They decode rows with the gfx950 hardware e2m1 -> fp16 conversion into separate even/odd fp16 tiles and chain the two dots, so no interleave shuffle is needed.Why
At high concurrency the FP8 KV + FP8 index cache runs out. On ATOM at c48 (AgentX
semianalysis_cc_traces_weka_062126, gpu-memory-utilization 0.8):This PR is the index half of the fix. The KV half is the next PR in the stack. KV block bytes for MiniMax-M3.1-Flash TP4 (from the server log):
Validation
MiniMax-M3.1-Flash-Quark-MXFP4, TP4, MI355X.
tests/test_minimax_m3_index_topk.pyfollows the new scorer signature.On its own, FP4 index does not speed decode up. At c32 (1200 s, NVFP4 KV), FP4 index gave 337.5 tok/s/GPU and P90 interactivity 79.2, against 340.1 and 87.1 with FP8 index. Its value is capacity, which matters at c48 (see the next PR).
🤖 Generated with Claude Code