[SM90] Add packed selected-KV sparse decode - #200
Open
xyz2606 wants to merge 1 commit into
Open
Conversation
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 an opt-in, two-stage packed selected-KV sparse decode path for the
GLM-5.2 / V3.2 FP8 MLA format on SM90:
pack_selected_kvgathers selected records from the paged KV cache into anopaque tile-major workspace.
flash_mla_with_packed_kvcacheconsumes that workspace with a packedsparse-decode specialization that avoids sparse index and page translation
on the attention critical path.
The existing native sparse-decode API and dispatch remain unchanged. The new
path is explicitly restricted to SM90 and is not enabled automatically.
Since this implementation introduces a compile-time packed-KV specialization in the existing SM90 sparse decode kernel, I’d appreciate maintainers’ guidance on whether you prefer the current shared-kernel approach, a policy/loader-based abstraction, or a separate packed-kernel implementation; I’m happy to restructure it in a follow-up revision based on your feedback.
Motivation
GLM-5.2 can share selected physical indices across multiple MLA layers. When
those indices are available before the layer that consumes them, the runtime
can move sparse address resolution and KV gathering into an earlier overlap
window.
The attention kernel can then read a contiguous packed workspace instead of
repeatedly:
Packing and attention are intentionally separate operations so a runtime can
overlap packing with preceding work such as MoE communication.
What changed
SM90 packing kernel
pack_selected_kvcopies each selected 656-byte V3.2 record byte-for-byte:The packer writes an opaque 64-token tile-major workspace. It supports a valid
selected-index prefix described by
topk_lengthand zero-fills invalid suffixrecords.
Callers may provide reusable contiguous
uint8storage usingget_packed_kv_workspace_size.Packed attention specialization
The packed H=64 and H=128 instantiations reuse FlashMLA's existing:
The specialization replaces the sparse index/page/gather loader with direct
tile-major loads and preserves partial-tail masking.
Scheduler policy
H=128 uses the same scheduler as native sparse decode.
H=64 uses the compact request-local scheduler selected by the L20X
experiments. For the measured full-prefix
topk=2048, 132-SMB*S_q=16regime, it falls back to the faster native scheduler.
This scheduler is used only by the opt-in packed helper and does not change
native sparse decode. The benchmark includes an identical-scheduler control to
isolate the packed-load kernel gain.
Python API
This PR adds:
get_packed_kv_workspace_sizeget_packed_mla_metadatapack_selected_kvflash_mla_with_packed_kvcacheSupported scope
The initial path is intentionally limited to:
d_qk=576;d_v=512;H in {64, 128};The API fails closed for unsupported architectures and shapes. SM100 is not
enabled because this implementation has only been evaluated on SM90.
L20X results
The repository-local benchmark was run on an NVIDIA L20X with 132 SMs using:
topk=2048;B={1,2,4,7,8};S_q={1,2,3,4,8,16};H={64,128};Packing is excluded from the attention-stage comparisons.
The unhidden result is included deliberately: this path is useful only when
the runtime can move most packing work outside the attention critical path.
This PR does not add automatic dispatch or change the default native path.
The H=64 hybrid policy selected the tuned scheduler in 26 cases and the native
fallback in four cases. The four fallback cases improved by approximately
6.5% to 7.4% compared with using the tuned scheduler unconditionally.
Correctness and benchmark coverage
The correctness test passes five cases covering:
The tests compare both output and LSE with native sparse decode and verify the
packed workspace layout.
Observed result:
The new CUDA kernels compiled for SM90 without register spills. The packer
used 18 registers, and both packed-attention instantiations used 168 registers.
Runtime follow-up
This PR contains the two FlashMLA kernels needed for the packed path, but
intentionally does not include current-token runtime orchestration.
A future vLLM integration can:
for example with a scatter operation;
Workspace pooling, CUDA stream placement, current-token updates, overlap
eligibility, and end-to-end TPOT measurements belong to that runtime
integration.
For
topk=2048, the workspace requires approximately 1.281 MiB per query row,so runtime dispatch should also enforce a workspace budget.
Non-goals
This PR does not:
setup.pyis changed only to register the three new CUDA source files.