[KV Cache] GLM-5.3-Flash: use the generic packed KV layout; CircularBufferSpec tail with speculative ring slots - #55219
[KV Cache] GLM-5.3-Flash: use the generic packed KV layout; CircularBufferSpec tail with speculative ring slots#55219ivanium wants to merge 4 commits into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The kpool tail is a one-block-per-request ring addressed by ``pos % ring``, which is exactly what CircularBufferSpec / CircularBufferManager already implement for Qwen's QSA ring. KpoolTailSpec only added a SlidingWindowSpec base (dragging in extra_retained_tokens tagging, sliding-window offload sizing and cascade heuristics for a 4-token "window") and an empty manager subclass. Drop both; the grouping code and the NIXL / Mooncake workers key on CircularBufferSpec instead. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yifan Qiao <yifanqiao@inferact.ai>
Each MTP step stashes 1 + num_speculative_tokens rows into the tail ring before acceptance is known. With a ring of exactly ``index_kpool`` slots the drafts that follow a pool-completing draft overwrite the committed keys of that pool, so when the completing draft is rejected the redo recompresses the boundary pool from wrong keys. Size the ring as ``kpool * cdiv(kpool + num_spec, kpool)`` (the QSA rule) and address it by ``pos % ring`` while the pool phase stays ``pos % kpool``. The seed and decode kernels take the ring size and the tail view's block and head strides explicitly, so the tail no longer has to be a dense ``[num_blocks, 2, ring, head_dim]`` allocation. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yifan Qiao <yifanqiao@inferact.ai>
3a0db34 to
7d545e1
Compare
7d545e1 to
e79dc1e
Compare
GLM-5.3-Flash carried its own KV cache grouping and tensor layout (``_get_kv_cache_groups_glm5_next`` / ``_glm5_next_tensor_layout``) plus matching special cases in the NIXL and Mooncake workers. It needed them because the MLA and indexer pages have incompatible sizes, which the generic code already handles by packing pages side by side inside each block (``_get_packed_kv_cache_groups``, as DeepSeek-V4 and Qwen3.8), but that layout is block-outermost and the worker cannot virtually split such a block into the 32/64-row pages the DeepGEMM paged-MQA and TRT-LLM sparse MLA kernels take. Re-page inside the kernels' callers instead: * The kpool indexer views its block as consecutive kernel pages with a stride in pages between blocks (``kpool_page_geometry``, ``_kpool_flat_page_view``) and the metadata builder expands the block table and slot mapping to those pages (``_indexer_page_table``), fed by a new ``block_stride_bytes`` builder hook. ``Glm5NextIndexerBackend`` takes the manager block as its kernel block and packed layouts. * The TRT-LLM sparse MLA backend accepts any multiple of 32 rows and re-pages larger blocks into ``MLA_KERNEL_PAGE_ROWS``-row pages (``_kernel_paged_view``); top-k indices are flat row ids so paging is free to change. * The packed block stride is rounded to the lcm of the re-paged kernel pages (``_packed_block_alignment_bytes``). With GLM's 1024-byte NoPE MLA rows and 132-byte indexer rows that is 1.03 MB per 13.4 MB block, about 4.7% of KV capacity. This removes ``storage_block_size`` and its plumbing, the GLM grouping and layout code, the NIXL virtual-transfer-page and covered-view handling, and the Mooncake tail rule. GLM keeps block 1152 and 3 Mamba groups; validated on TP4-to-TP4 NIXL PD with GSM8K 0.9727 / 0.9742. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yifan Qiao <yifanqiao@inferact.ai>
``MambaSpec.real_page_size_bytes`` has no caller once the GLM tensor layout is gone, and the manager module's logger was never used. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yifan Qiao <yifanqiao@inferact.ai>
e79dc1e to
6712aa1
Compare
|
This pull request has merge conflicts that must be resolved before it can be |
|
I'm preparing a focused fix for ordinary 64-row V3.2 sparse MLA/indexer packing. At the current head, #55219's packed alignment is tied to kernel re-paging, while ordinary heterogeneous row widths still require a common packed-block row alignment. Would it make sense for a shared alignment helper to carry both requirements? |
|
Opened #55528 with the focused ordinary-row alignment change. Happy to coordinate the shared allocator helper if useful. |
Purpose
Follow-up to #53906 (GLM-5.3-Flash). Remove the model-specific KV cache grouping / tensor layout and the matching NIXL and Mooncake special cases by routing GLM through the generic packed (block-outermost) layout that DeepSeek-V4 and Qwen3.8-Next already use, and fix two issues in the kpool tail ring.
KpoolTailSpecis dropped; the tail is a plainCircularBufferSpec(its manager already wasCircularBufferManager).kpool * cdiv(kpool + num_spec, kpool)as the QSA ring does. With exactlykpoolslots, a rejected pool-completing draft left the drafts behind it overwriting the committed keys the redo needs (covered by new CUDA kernel and index-level tests). The seed/decode tail kernels (NVIDIA and AMD) take the ring size and the tail view's strides._get_kv_cache_groups_glm5_next/_glm5_next_tensor_layouthandled with a hand-rolled layer-outer layout,storage_block_size, worker-side virtual block splitting and NIXL "dense virtual transfer pages". The generic packed path already handles mixed page sizes, but a block-outermost block cannot be split by the worker into the 32/64-row pages DeepGEMM paged-MQA and the TRT-LLM sparse MLA kernel take. This PR re-pages inside the kernels' callers instead:kpool_page_geometry/_kpool_flat_page_view/_indexer_page_tablefor the indexer (fed by ablock_stride_bytesbuilder hook),_kernel_paged_viewfor the FlashInfer sparse MLA impls (TRT-LLM on SM100 nowMultipleOf(32), 32-row pages; SM120 64-row pages; SM90 uses page size 1 so it only needs the row stride and no longer forces the LBHNC layout), and the packed block stride is aligned to the lcm of the kernel pages (_packed_block_alignment_bytes, only when a layer needs re-paging; DeepSeek-V4 and Qwen are unaffected). The page size a backend re-pages to is declared by a newAttentionBackend.get_kernel_page_rows()and recorded onMLAAttentionSpec.kernel_page_rows, so the layout code does not hard-code kernel constants. GLM keeps block 1152 and 3 Mamba groups; the alignment costs ~4.7% KV capacity on GB200 TP4.kv_cache_utils.pyand the NIXL worker carry no GLM-specific code path any more. The NIXL wire layout is unchanged (the removed virtual pages were never part of a release), so noNIXL_CONNECTOR_VERSIONbump.Duplicate check: no open PR touches the GLM KV layout,
KpoolTailSpec,storage_block_sizeor the NIXL virtual transfer pages.Test Plan
GLM-5.3-Flash, TP4-to-TP4 NIXL PD on GB200, GSM8K 5-shot x2 (mqa), no MTP:
Test Result
indicesits schedule was built with ([Bugfix] GLM-5.3-Flash: launch the kpool paged MQA logits in the varlen mode its schedule was built with #55270, independent of this PR). On DeepGEMM 2.5.0 that deadlocks GLM MTP decode within minutes; on the pinned 2.6.1 it is tolerated. With [Bugfix] GLM-5.3-Flash: launch the kpool paged MQA logits in the varlen mode its schedule was built with #55270 applied on top of this branch: single-node TP4 MTP3 GSM8K 0.9723 / 0.9738 and TP4-to-TP4 NIXL PD + MTP3 0.9708 / 0.9719 on DeepGEMM 2.5.0; on the pinned 2.6.1 single-node MTP3 passes in eager (0.9704 / 0.9719) and with CUDA graphs (0.97). All with 0 request errors. ROCm kernels mirror the CUDA change but were not run. SM90 and SM120 are covered by unit tests only (no H100 / RTX Pro available): the sparse MLA wiring and the kpool block alignment (32-state indexer pages on SM90/SM100, 64 on SM120, matching the pinned DeepGEMM'sget_paged_mqa_logits_metadataconstraints). GLM on SM120 additionally needs the rope-free sparse MLA path tracked in GLM-5.3-Flash (glm5_next): no SM120 sparse-MLA path for rope-free MLA (qk_rope_head_dim=0) — three failure modes on RTX PRO 6000 #53963.AI assistance (Claude Code) was used for analysis, implementation and review; the submitter reviewed every line.
🤖 Generated with Claude Code