Repository navigation
Conversation
The breakable prefill graph runner for Qwen3.8-Flash-Next (Qwen4-Exp: Qwen4ExpForConditionalGeneration and its MTP draft, Qwen4ExpForCausalLMMTP) refuses every batch that carries multimodal inputs, on the target and on the MTP draft alike, so image requests always run eager prefill even when the breakable prefill backend is enabled. Key the refusal on whether speculative decoding is enabled instead of on the worker's role. Without speculative decoding there is no draft runner and multimodal batches are replay-eligible: the eager outer forward builds the merged text and vision embeddings and replay copies them into the captured body's static input_embeds slot, the same path text batches already take. With speculative decoding enabled the behavior is unchanged and the target keeps refusing them. Dropping only the target's refusal would let DP ranks disagree on replay versus eager for the draft runner: its verdict is the target's schedule-time vote, which consults only the target runner, combined with the draft's own rank-local refusal, so a rank holding images would run its draft eager while the other ranks replay theirs. That is the disagreement can_replay_locally exists to prevent. The predicate is the speculative algorithm rather than the presence of a draft model, so an algorithm without one (NGRAM) also keeps refusing. The breakable prefill backend is the default on CUDA and opt-in elsewhere, so on CUDA this applies by default to Qwen3.8-Flash-Next without speculative decoding. The private _qwen_bcg_mtp_draft flag had no other reader and is replaced by _qwen_bcg_multimodal_eager. Tests cover the flag across backend, architecture, worker role and speculative algorithm (including NGRAM), the DP vote with one image rank and one text rank with the refusal on and off, and the forward-time gate for image and text batches. Fixtures that set the removed flag are updated. Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Rony Leppänen <rony.leppanen@amd.com>
4 of 5 tasks
Keep only the rows that exercise the speculative-algorithm predicate (none, EAGLE, NGRAM) and drop the rows and the hc_sidechannel assertion that re-tested unchanged code. Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Rony Leppänen <rony.leppanen@amd.com>
rkarhila-amd
approved these changes
Oct 27, 2026
rkarhila-amd
left a comment
There was a problem hiding this comment.
I don't see any issues with this code.
Go ahead and open for code owner review.
eppaneamd
marked this pull request as ready for review
October 27, 2026 21:56
eppaneamd
requested review from
Fridge003,
Ying1123,
hnyls2002,
ispobock and
merrymercy
as code owners
October 27, 2026 21:56
This comment has been minimized.
This comment has been minimized.
Author
This branch has not been deployed
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.
Motivation
With
--cuda-graph-backend-prefill breakable, the prefill runner refuses graph replay for every Qwen3.8-Flash-Next (Qwen4-Exp) batch that carries multimodal inputs, so image prefills always run eager.Scope: this enables graph replay for image prefills in deployments without speculative decoding. With speculative decoding enabled (any algorithm, including NGRAM), behavior is unchanged.
input_embedsalready replay under breakable graphs (Enable Kimi multimodal breakable prefill CUDA graph replay #31391): the eager outer forward builds the merged text and vision embeddings, and replay copies them into the captured static slot, as for text batches.This PR keys the refusal on whether speculative decoding is enabled, a launch-time property identical on every rank. Without speculative decoding, image batches become replay-eligible; with any speculative algorithm (including NGRAM), behavior is unchanged. No new flag, environment variable or API.
Modifications
python/sglang/srt/model_executor/runner/prefill_cuda_graph_runner.py(+8/-4): replace_qwen_bcg_mtp_draft(no other reader) with_qwen_bcg_multimodal_eager = qwen_bcg and model_runner.spec_algorithm.is_speculative(), and gate multimodal batches on it.test/registered/unit/model_executor/test_prefill_cuda_graph_runner.py: flag derivation for no speculative decoding, EAGLE and NGRAM.test/registered/unit/managers/scheduler_components/test_dp_attn.py: DP vote with one image rank and one text rank, refusal on and off.test/registered/unit/configs/test_multimodal_piecewise_cuda_graph.py: forward-time gate for image and text batches.test/registered/unit/model_executor/test_prefill_cuda_graph_runner_helpers.py: drop fixture lines for the removed flag.The breakable prefill backend is the default on CUDA, so there this applies by default to Qwen3.8-Flash-Next without speculative decoding. On ROCm it is opt-in.
Accuracy Tests
Mean probability of the gold answer over 805 MMMU validation items, unpatched main vs this commit with breakable prefill graphs, 2 server launches per arm:
A greedy-output probe (16 requests) completed in every server launch; its outputs are not used as an accuracy comparison.
Speed Tests and Profiling
Setup
lmsysorg/sglang-rocm:v0.5.22-rocm724-mi35x-20261024, SGLang tree13b7ef75c5with this commit applied (prefill_cuda_graph_runner.pyis unchanged between that tree and this PR's base), torch 2.11.0+rocm7.2.amd/Qwen3.8-Flash-Next-Quark-MXFP4(revisionb2091c38), MTP off.--attention-backend aiter --linear-attn-backend triton --context-length 8192 --max-running-requests 128 --disable-radix-cache --mm-enable-dp-encoder.--cuda-graph-backend-prefill breakable.sglang.bench_serving, one 512x512 image per request, 1024 input / 128 output tokens (range ratio 0.8), prompts = 10x concurrency; 2 server launches per arm (order A, explicit, default, default, explicit, A), 2 measured runs per row after a warm-up pass.Mean change over concurrency 16-64: +20.9% (explicit), +21.0% (default), SE 0.55 pp. SE: standard error of the change in percentage points, estimated from baseline-vs-baseline (A/A) runs with the same procedure; a change beyond about 2 SE is outside run-to-run noise.
Checklist
ruff checkandruff format --checkclean on the five files.Notes
input_embedsreplay).CI States
Latest PR Test (Base): ❌ Run #41000722234
Latest PR Test (Extra): ❌ Run #41000722037
Latest PR Test (AMD ROCm 10): ✅ Run #41000722040