Skip to content

Allow prefill breakable CUDA graph for Qwen3.5 via multimodal opt-in allowlist - #30620

Merged
Fridge003 merged 4 commits into
sgl-project:mainfrom
YAMY1234:bcg-multimodal-allowlist-qwen35
Jul 14, 2026
Merged

Fridge003 merged 4 commits into
sgl-project:mainfrom
YAMY1234:bcg-multimodal-allowlist-qwen35

Conversation

@YAMY1234

@YAMY1234 YAMY1234 commented Jul 9, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

Since #29458, breakable CUDA graph (BCG) is the default prefill CUDA graph backend on CUDA, but the generic "multimodal model" rule in _disable_breakable_cudagraph_if_incompatible turns it off for every arch in multimodal_model_archs. Qwen3.5 (Qwen3_5[Moe]ForConditionalGeneration) is caught by this rule even for text-only serving, although its GDN/GQA prefill path fully supports BCG capture/replay.

The failure mode the rule protects against ("multimodal prefill replay faults") is real: the captured graph embeds from input_ids only, while multimodal batches merge mm embeddings in the outer model wrapper, which capture bypasses — replaying them silently drops image inputs. The existing can_run_graph guard only covered input_embeds / replace_embeds; this PR extends it to batches carrying mm_inputs (caught by test_vlm_tp4.py MMMU dropping to 0.50 on the first CI run of this PR; multimodal batches now fall back to eager prefill, which is today's behavior).

Modifications

Mirror the existing tc_piecewise opt-in pattern (multimodal_piecewise_cuda_graph_supported_model_archs) with a BCG-specific allowlist:

  • model_config.py: add multimodal_breakable_cuda_graph_supported_model_archs (Qwen3.5 dense + MoE) and the corresponding ModelConfig field.
  • server_args.py: the BCG "multimodal model" rule becomes is_multimodal and not is_multimodal_breakable_cuda_graph_supported.
  • prefill_cuda_graph_runner.py: can_run_graph rejects batches carrying mm_inputs, so multimodal batches run eager prefill while text-only batches replay the graph. mm_inputs persists on the request until it finishes, so every prefill chunk of a multimodal request is covered.

No behavior change for any arch not on the allowlist.

Accuracy Tests

Speed Tests and Profiling

Qwen3.5-397B-A17B-FP8, single node TP4 (GB200), 1k1k random dataset, closed-loop client (range-ratio 0.8, num-prompts 10×conc, request-rate inf). Server args follow the InferenceX/InferenceMAX qwen3.5 fp8 configs (trtllm_mha attention, flashinfer_trtllm MoE, fp8_e4m3 KV cache, --enable-symm-mem, --disable-radix-cache). "BCG off" = same build with --disable-prefill-cuda-graph, which is the effective status quo for Qwen3.5 today.

Config Concurrency BCG on: total tok/s / p50 TTFT BCG off: total tok/s / p50 TTFT Δ throughput Δ TTFT
TP4 4 1241.3 / 208.6 ms 1139.6 / 361.0 ms +8.9% −42.2%
TP4 + EAGLE MTP 16 4955.4 / 464.6 ms 4382.8 / 540.6 ms +13.1% −14.1%
TP4 64 7369.1 / 466.8 ms 6758.5 / 532.9 ms +9.0% −12.4%

EAGLE accept length is unchanged between the two arms (2.956 vs 2.931). One-time capture cost: ~41 s at startup, 1.83 GB per GPU (chunked-prefill 16384 bucket set).

Note: the numbers above were measured with #27918 (restores the fused Triton MRoPE path under BCG) applied on top; that fix is complementary and tracked separately.

Unit test

test/registered/unit/server_args/test_server_args.py::TestBreakableCudaGraphMultimodalAllowlist covers the new rule (allowlisted arch keeps breakable, non-allowlisted multimodal arch resolves to disabled) and allowlist membership. Verified together with the neighboring TestCudaGraphDisaggregationRoles: 7 passed.

Checklist


CI States

Latest PR Test (Base): ✅ Run #29230286789
Latest PR Test (Extra): ❌ Run #29230286551

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for breakable CUDA graphs in specific multimodal model architectures, specifically Qwen 3.5 and Qwen 3.5 MoE. It adds a configuration property and helper function to identify supported architectures and updates the server arguments to allow breakable CUDA graphs for these allowlisted multimodal models. There are no review comments, and I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@YAMY1234
YAMY1234 marked this pull request as ready for review July 9, 2026 08:30

@Oasis-Git Oasis-Git 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.

Could you add a CI test?

…allowlist

The generic "multimodal model" rule in _disable_breakable_cudagraph_if_incompatible
disables prefill BCG for every arch in multimodal_model_archs. Qwen3.5
(Qwen3_5[Moe]ForConditionalGeneration) is caught by it even for text-only
serving, although its GDN/GQA prefill path fully supports BCG capture/replay.

Mirror the existing tc_piecewise opt-in pattern
(multimodal_piecewise_cuda_graph_supported_model_archs) with a BCG-specific
allowlist. The replay-time guard is unchanged: batches carrying
input_embeds/replace_embeds are rejected by can_run_graph and fall back to
eager, so vision requests never replay the text-only graph.

Add unit tests covering the rule (allowlisted arch keeps breakable,
non-allowlisted multimodal arch is disabled) and allowlist membership.
@YAMY1234
YAMY1234 force-pushed the bcg-multimodal-allowlist-qwen35 branch from 46d66a5 to 3d3cf25 Compare July 9, 2026 21:27
@YAMY1234

YAMY1234 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator Author

Could you add a CI test?

Sure — added a unit test for the gate logic: TestBreakableCudaGraphMultimodalAllowlist

class TestBreakableCudaGraphMultimodalAllowlist(CustomTestCase):

(allowlisted archs keep breakable; other multimodal archs still resolve to disabled).

E2E is already covered by existing CI — these run per-commit on B200 (base-c) with a gsm8k >= 0.95 gate, and neither sets any prefill CUDA-graph flag, so with this PR they run under BCG by default:

register_cuda_ci(est_time=720, stage="base-c", runner_config="4-gpu-b200")

register_cuda_ci(est_time=740, stage="base-c", runner_config="4-gpu-b200")

The nightly FP8 suite picks it up as well:

register_cuda_ci(est_time=1800, suite="nightly-8-gpu-common", nightly=True)

@YAMY1234

YAMY1234 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator Author

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci CI: run the baseline test suite on this PR label Jul 9, 2026
The captured prefill graph embeds from input_ids only; multimodal
batches merge mm embeddings in the outer model wrapper, which graph
capture bypasses, so replaying them silently drops image inputs
(caught by test_vlm_tp4.py MMMU dropping to 0.50 vs the 0.65 threshold
once the allowlist enabled BCG for Qwen3.5).

can_run_graph already rejects input_embeds/replace_embeds batches; add
the same rejection for batches carrying mm_inputs so they fall back to
eager prefill, while text-only batches keep the captured graph.
mm_inputs persists on the request until it finishes, so every prefill
chunk of a multimodal request is covered.
@YAMY1234

Copy link
Copy Markdown
Collaborator Author

/rerun-failed-ci

@YAMY1234

Copy link
Copy Markdown
Collaborator Author

/rerun-test test/registered/vlm/test_vlm_tp4.py test/registered/models_e2e/test_qwen35_fp4_flashinfer.py test/registered/models_e2e/test_qwen35_fp4_mtp.py test/registered/unit/server_args/test_server_args.py

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Rebase Required Before Re-run

A major update has landed on main. Your PR is diverged relative to required base commit cbcbef6.

Re-run was not dispatched. What to do:

  • Rebase your branch onto the latest main and push again
  • Follow issue #21065 for context
  • CI-fix PRs may request the bypass-maintenance label to skip this check

@YAMY1234

Copy link
Copy Markdown
Collaborator Author

/rerun-test test/registered/vlm/test_vlm_tp4.py test/registered/models_e2e/test_qwen35_fp4_flashinfer.py test/registered/models_e2e/test_qwen35_fp4_mtp.py test/registered/unit/server_args/test_server_args.py

@github-actions

github-actions Bot commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-test test/registered/vlm/test_vlm_tp4.py test/registered/models_e2e/test_qwen35_fp4_flashinfer.py test/registered/models_e2e/test_qwen35_fp4_mtp.py test/registered/unit/server_args/test_server_args.py:

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

cd test/ && python3 registered/vlm/test_vlm_tp4.py

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

cd test/ && python3 registered/models_e2e/test_qwen35_fp4_flashinfer.py
cd test/ && python3 registered/models_e2e/test_qwen35_fp4_mtp.py

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

cd test/ && python3 registered/unit/server_args/test_server_args.py

@Fridge003
Fridge003 merged commit 41ad0d9 into sgl-project:main Jul 14, 2026
148 of 167 checks passed
Chronostasys pushed a commit to MindLab-Research/sglang that referenced this pull request Aug 24, 2026
@YAMY1234
YAMY1234 deleted the bcg-multimodal-allowlist-qwen35 branch August 25, 2026 16:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bypass-fastfail run-ci CI: run the baseline test suite on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants