Skip to content

[refactor] Fold FrozenKVMTPCudaGraphRunner onto the shared DecodeCudaGraphRunner base - #28081

Merged
ch-wan merged 1 commit into
mainfrom
cheng/refactor/fold-frozen-kv-mtp-cuda-graph-runner
Jun 12, 2026
Merged

ch-wan merged 1 commit into
mainfrom
cheng/refactor/fold-frozen-kv-mtp-cuda-graph-runner

Conversation

@ch-wan

@ch-wan ch-wan commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Motivation

FrozenKVMTPCudaGraphRunner was the last speculative cuda-graph runner still standalone on the legacy raw torch.cuda.CUDAGraph / self.graphs surface. It hand-rolled the capture loop, bucket padding, and graph-pool management that DecodeCudaGraphRunner and the runner_backend/ backends now own — the same machinery the EAGLE draft runners already share after the cuda-graph runner/backend refactor (#23906). This left the frozen-KV MTP draft loop as the lone duplicate of that scaffolding.

Fold it onto DecodeCudaGraphRunner, mirroring EAGLEDraftCudaGraphRunner, so the frozen-KV MTP draft step reuses the shared capture/replay path and drops its bespoke raw-graph code.

Modifications

  • FrozenKVMTPCudaGraphRunner now subclasses DecodeCudaGraphRunner (no super().__init__; it sets the parent's capture-contract fields directly and disables the inapplicable decode paths via compile_bs=[] / enable_pdmux=False / record_nolora_graph=False / is_dllm=False).
  • Capture/replay route through self.backend = resolve_decode_backend(self):
    • capture_one_batch_sizecapture_one_shape(size, forward, stream_idx, variant_label), driven by the inherited _capture_one_stream loop; it calls backend.capture_one (which owns the two warmup passes + post_warmup_hook).
    • replay calls backend.replay via _replay_graph; _make_graph_key returns ShapeKey(size=bs).
  • Inherits capture() / _capture_one_stream() and _pad_to_bucket() from the base; removes the hand-rolled _create_graph / _capture_init / _capture_graph / _replay, the self.graphs / self.output_buffers dicts, the bisect padding, and the legacy graph-pool imports.
  • Frozen-KV-MTP-specific behavior is preserved verbatim inside the overrides: the target-KV-pool swap around capture, the topk*topk bucket divisor in can_run / replay, the expanded-bs (request_bs * topk) bookkeeping, the worker's _init_frozen_kv_metadata_{capture,replay}_cuda_graph helpers, the FrozenKVMTPDraftInput spec_info, and the 3-tuple replay output.

Behavior-preserving by construction; net +22 lines (legacy machinery removed, backend wiring added).

Accuracy Tests

Frozen-KV MTP draft acceptance is covered by test/registered/spec/test_frozen_kv_mtp.py (GSM8K + average spec accept length on google/gemma-4-E4B-it, CUDA graph enabled, topk 1 and 3). Local structural checks: the module compiles, imports as a non-abstract DecodeCudaGraphRunner subclass with all runner methods resolving (capture() inherited; capture_one_shape / replay / can_run / _make_graph_key / _replay_graph overridden), and no legacy raw-CUDAGraph surface remains.

Speed Tests and Profiling

Negligible. Capture runs once at startup; the steady-state replay path is the same backend graph replay as before — same captured graph, same buffers, same per-step draft logic. No kernel or hot-path code changed.

Checklist


CI States

Latest PR Test (Base): 🚫 Run #27447122392
Latest PR Test (Extra): ❌ Run #27447122201

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@ch-wan

ch-wan commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator Author

/tag-and-rerun-ci

@ch-wan

ch-wan commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator Author

/rerun-test test_frozen_kv_mtp.py test_resolve_swa_kv_pool.py

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Results for /rerun-test test_frozen_kv_mtp.py test_resolve_swa_kv_pool.py:

🚀 1-gpu-h100 (2 tests): ✅ View workflow run

cd test/ && python3 registered/spec/test_frozen_kv_mtp.py
cd test/ && python3 registered/unit/spec/test_resolve_swa_kv_pool.py

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 504badc883

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@@ -174,53 +205,24 @@ def can_run(self, forward_batch: ForwardBatch):
)

is_bs_supported = (
cuda_graph_bs in self.graphs
self.backend.can_run(forward_batch, cuda_graph_bs)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use ShapeKey when checking captured buckets

When --disable-cuda-graph-padding is enabled, this passes the raw integer cuda_graph_bs to backend.can_run, but this runner captures and replays graphs under ShapeKey(size=...) (see the nearby _make_graph_key usage in capture/replay). The full and breakable backends key their _graphs dictionaries by that exact object, so exact-size frozen-KV MTP batches that were captured will be reported unsupported and will fall back instead of using the CUDA graph.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in a2feafc. This was a real regression from the fold: pre-fold the runner kept self.graphs keyed by the int bs, so cuda_graph_bs in self.graphs worked under --disable-cuda-graph-padding. The fold moves graph storage to the backend, which keys _graphs by ShapeKey, so the raw int never matched and exact-size batches fell back. can_run now passes self._make_graph_key(cuda_graph_bs) (matching the BaseCudaGraphBackend.can_run(forward_batch, shape_key) contract and how capture/replay key the table), restoring the exact-size membership check. Verified by the FA4 frozen-KV MTP runner-mode unit test.

@ch-wan
ch-wan force-pushed the cheng/refactor/fold-frozen-kv-mtp-cuda-graph-runner branch from 504badc to db0be2e Compare June 12, 2026 20:52
@ch-wan
ch-wan force-pushed the cheng/refactor/fold-frozen-kv-mtp-cuda-graph-runner branch from db0be2e to a2feafc Compare June 12, 2026 20:56

@kpham-sgl kpham-sgl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty!

@ch-wan
ch-wan force-pushed the cheng/refactor/fold-frozen-kv-mtp-cuda-graph-runner branch 2 times, most recently from f911a2b to ac878d1 Compare June 12, 2026 22:32
@ch-wan

ch-wan commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator Author

/rerun-test registered/attention/unittests/* registered/spec/*

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Results for /rerun-test registered/attention/unittests/* registered/spec/*:

🚀 1-gpu-5090 (8 tests): ✅ View workflow run

cd test/ && python3 registered/attention/unittests/dense/test_extend_init_contract.py
cd test/ && python3 registered/spec/dflash/test_dflash.py
cd test/ && python3 registered/spec/eagle/test_spec_eagle.py
cd test/ && python3 registered/spec/eagle/test_spec_eagle_page.py
cd test/ && python3 registered/spec/eagle/test_spec_eagle_topk.py
cd test/ && python3 registered/spec/eagle/test_spec_eagle_topk_page.py
cd test/ && python3 registered/spec/eagle/test_spec_eagle_triton.py
cd test/ && python3 registered/spec/utils/test_build_eagle_tree.py

🚀 4-gpu-b200 (29 tests): ✅ View workflow run

cd test/ && python3 registered/attention/unittests/dense/test_fa3.py
cd test/ && python3 registered/attention/unittests/dense/test_fa4.py
cd test/ && python3 registered/attention/unittests/dense/test_flashinfer.py
cd test/ && python3 registered/attention/unittests/dense/test_flex_attention.py
cd test/ && python3 registered/attention/unittests/dense/test_hybrid_attn.py
cd test/ && python3 registered/attention/unittests/dense/test_tbo.py
cd test/ && python3 registered/attention/unittests/dense/test_torch_native.py
cd test/ && python3 registered/attention/unittests/dense/test_triton.py
cd test/ && python3 registered/attention/unittests/dense/test_trtllm_mha.py
cd test/ && python3 registered/attention/unittests/dsa/test_dsa.py
cd test/ && python3 registered/attention/unittests/dsv4/test_deepseek_v4.py
cd test/ && python3 registered/attention/unittests/dual_chunk/test_dual_chunk_flash_attn.py
cd test/ && python3 registered/attention/unittests/gdn/test_flashinfer.py
cd test/ && python3 registered/attention/unittests/gdn/test_torch_native.py
cd test/ && python3 registered/attention/unittests/gdn/test_triton.py
cd test/ && python3 registered/attention/unittests/kda/test_triton.py
cd test/ && python3 registered/attention/unittests/lightning/test_triton.py
cd test/ && python3 registered/attention/unittests/mamba/test_mamba2.py
cd test/ && python3 registered/attention/unittests/mla/test_cutlass_mla.py
cd test/ && python3 registered/attention/unittests/mla/test_flashinfer.py
cd test/ && python3 registered/attention/unittests/mla/test_flashmla.py
cd test/ && python3 registered/attention/unittests/mla/test_tokenspeed_mla.py
cd test/ && python3 registered/attention/unittests/mla/test_triton.py
cd test/ && python3 registered/attention/unittests/mla/test_trtllm_mla.py
cd test/ && python3 registered/attention/unittests/swa/test_flashinfer.py
cd test/ && python3 registered/attention/unittests/swa/test_torch_native.py
cd test/ && python3 registered/attention/unittests/swa/test_triton.py
cd test/ && python3 registered/spec/eagle/test_deepseek_v3_fp4_mtp_small.py
cd test/ && python3 registered/spec/eagle/test_eagle_infer_beta_dp_attention.py

🚀 1-gpu-h100 (38 tests): ✅ View workflow run

cd test/ && python3 registered/attention/unittests/dense/test_fa3.py
cd test/ && python3 registered/attention/unittests/dense/test_fa4.py
cd test/ && python3 registered/attention/unittests/dense/test_flashinfer.py
cd test/ && python3 registered/attention/unittests/dense/test_flex_attention.py
cd test/ && python3 registered/attention/unittests/dense/test_hybrid_attn.py
cd test/ && python3 registered/attention/unittests/dense/test_tbo.py
cd test/ && python3 registered/attention/unittests/dense/test_torch_native.py
cd test/ && python3 registered/attention/unittests/dense/test_triton.py
cd test/ && python3 registered/attention/unittests/dense/test_trtllm_mha.py
cd test/ && python3 registered/attention/unittests/dsa/test_dsa.py
cd test/ && python3 registered/attention/unittests/dsv4/test_deepseek_v4.py
cd test/ && python3 registered/attention/unittests/dual_chunk/test_dual_chunk_flash_attn.py
cd test/ && python3 registered/attention/unittests/gdn/test_flashinfer.py
cd test/ && python3 registered/attention/unittests/gdn/test_torch_native.py
cd test/ && python3 registered/attention/unittests/gdn/test_triton.py
cd test/ && python3 registered/attention/unittests/hybrid_linear/test_flashinfer_mla_chunk_metadata.py
cd test/ && python3 registered/attention/unittests/kda/test_triton.py
cd test/ && python3 registered/attention/unittests/lightning/test_triton.py
cd test/ && python3 registered/attention/unittests/mamba/test_mamba2.py
cd test/ && python3 registered/attention/unittests/mla/test_cutlass_mla.py
cd test/ && python3 registered/attention/unittests/mla/test_flashinfer.py
cd test/ && python3 registered/attention/unittests/mla/test_flashmla.py
cd test/ && python3 registered/attention/unittests/mla/test_tokenspeed_mla.py
cd test/ && python3 registered/attention/unittests/mla/test_triton.py
cd test/ && python3 registered/attention/unittests/mla/test_trtllm_mla.py
cd test/ && python3 registered/attention/unittests/swa/test_flashinfer.py
cd test/ && python3 registered/attention/unittests/swa/test_torch_native.py
cd test/ && python3 registered/attention/unittests/swa/test_triton.py
cd test/ && python3 registered/spec/eagle/test_adaptive_speculative.py
cd test/ && python3 registered/spec/eagle/test_eagle_constrained_decoding.py
cd test/ && python3 registered/spec/eagle/test_spec_eagle_fa3.py
cd test/ && python3 registered/spec/eagle/test_spec_eagle_parity.py
cd test/ && python3 registered/spec/eagle/test_spec_eagle_stress.py
cd test/ && python3 registered/spec/test_frozen_kv_mtp.py
cd test/ && python3 registered/spec/test_spec_ngram.py
cd test/ && python3 registered/spec/test_spec_ngram_extra.py
cd test/ && python3 registered/spec/test_spec_standalone.py
cd test/ && python3 registered/spec/test_spec_standalone_extra.py

🚀 ubuntu-latest (1 test): ✅ View workflow run

cd test/ && python3 registered/attention/unittests/swa/test_swa_out_cache_loc.py

🚀 4-gpu-h100 (1 test): ❌ View workflow run

cd test/ && python3 registered/spec/eagle/test_eagle_dp_attention.py

🚀 8-gpu-b200 (1 test): ✅ View workflow run

cd test/ && python3 registered/spec/eagle/test_eagle_infer_beta_dp_attention_large.py

🚀 2-gpu-h100 (3 tests): ✅ View workflow run

cd test/ && python3 registered/spec/test_constrained_decoding_spec_reasoning.py
cd test/ && python3 registered/spec/test_gemma4_mtp_26b_a4b_extra.py
cd test/ && python3 registered/spec/test_gemma4_mtp_31b_extra.py

@ch-wan
ch-wan merged commit 3a1417a into main Jun 12, 2026
97 of 146 checks passed
@ch-wan
ch-wan deleted the cheng/refactor/fold-frozen-kv-mtp-cuda-graph-runner branch June 12, 2026 23:55
kpham-sgl added a commit that referenced this pull request Jun 22, 2026
Resolve conflicts from spec v2 refactor:
- frozen_kv_mtp_worker.py: removed (replaced by frozen_kv_mtp_worker_v2.py
  in #27607); ported trtllm_mha draft-attn-backend branch into the v2 worker.
- frozen_kv_mtp_cuda_graph_runner.py: adopt shared DecodeCudaGraphRunner
  surface (_replay_graph + _make_graph_key) from #28081 / #28384.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Chronostasys pushed a commit to MindLab-Research/sglang that referenced this pull request Aug 24, 2026
jakki-amd pushed a commit to jakki-amd/sglang that referenced this pull request Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants