Skip to content

Share BCG output buffers across capture sizes - #27659

Merged
Fridge003 merged 2 commits into
mainfrom
lmzheng/bcg-shared-output-buffer
Jun 10, 2026
Merged

Fridge003 merged 2 commits into
mainfrom
lmzheng/bcg-shared-output-buffer

Conversation

@merrymercy

@merrymercy merrymercy commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Reuse one maximum-size output buffer across breakable CUDA graph capture sizes.
  • Store sliced views for smaller capture sizes.
  • Copy smaller capture outputs into the shared buffer during capture.
  • Handle optional None outputs when sharing captured output buffers.

Verification

  • git diff --check -- python/sglang/srt/model_executor/breakable_cuda_graph_runner.py
  • python3 -m py_compile python/sglang/srt/model_executor/breakable_cuda_graph_runner.py
  • black --check python/sglang/srt/model_executor/breakable_cuda_graph_runner.py
  • ruff check --select=F401,F821 python/sglang/srt/model_executor/breakable_cuda_graph_runner.py

Original commits

  • a2c14728a
  • e0747b8ee

CI States

Latest PR Test (Base): ✅ Run #27193490863
Latest PR Test (Extra): ❌ Run #27193490917

Reuse one maximum-size output buffer while capturing breakable CUDA graph token buckets, and store sliced views for smaller capture sizes.

Co-authored-by: Lianmin Zheng <lianminzheng@gmail.com>
@merrymercy

Copy link
Copy Markdown
Contributor Author

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci label Jun 9, 2026

@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 a shared output buffer mechanism in breakable_cuda_graph_runner.py to optimize CUDA graph capture across different token sizes, adding helper methods _slice_output and _copy_output_to_buffer to manage output slicing and copying. The review feedback correctly identifies potential TypeError issues if the model's forward pass returns None for optional outputs, and suggests robustly handling None values in both helper methods.

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.

Comment thread python/sglang/srt/model_executor/breakable_cuda_graph_runner.py
Comment thread python/sglang/srt/model_executor/breakable_cuda_graph_runner.py
Co-authored-by: Lianmin Zheng <lianminzheng@gmail.com>
@merrymercy

Copy link
Copy Markdown
Contributor Author

/tag-and-rerun-ci

@Fridge003
Fridge003 merged commit 165331a into main Jun 10, 2026
210 of 228 checks passed
@Fridge003
Fridge003 deleted the lmzheng/bcg-shared-output-buffer branch June 10, 2026 03:33
Fridge003 pushed a commit that referenced this pull request Jun 10, 2026
…ure sizes (#27659) (#27756)

Co-authored-by: Lianmin Zheng <lianminzheng@gmail.com>
Oasis-Git added a commit to Oasis-Git/sglang that referenced this pull request Jun 11, 2026
…class

The cg-refactor's cuda-graph dict key was `int | str` produced by
_make_graph_key(bs, stream_idx, variant_label) — e.g. `bs` for plain
decode, `f"{stream_idx}_{bs}"` for pdmux, `f"{lora}_{stream_idx}_{bs}"`
for LoRA-variant capture. The str form was opaque and conflated three
independent axes.

Replace with a frozen dataclass:

    @DataClass(frozen=True)
    class ShapeKey:
        size: int                          # bs * num_tokens_per_bs (decode)
                                           # or num_tokens (prefill)
        stream_idx: Optional[int] = None
        variant_label: Optional[str] = None

`size` fuses bs and num_tokens_per_bs (matches the existing convention
that bs and token count are unified). `frozen=True` gives us __eq__ /
__hash__ for free, so it drops into _graphs / _outputs dict lookups
unchanged.

This also lets BCG's output-buffer sharing (sgl-project#27659) read shape_key.size
directly — the redundant num_tokens kwarg added to capture_one in the
previous commit goes away, and the abstract surface across all
backends (BCG / Full / TcPiecewise / NPU) is back to a single typed
shape_key argument.

Touches:
- new python/sglang/srt/model_executor/runner/shape_key.py
- decode / prefill runners construct ShapeKey at capture and replay
- 3 EAGLE speculative runners override _make_graph_key to return ShapeKey
- 4 backends (base, BCG, Full, TcPiecewise, NPU) type shape_key: ShapeKey
- BCG capture_one drops num_tokens kwarg; reads shape_key.size

Verified on gpt-oss-20b, 1x B200, --chunked-prefill-size 16384,
--cuda-graph-backend-prefill breakable: prefill BCG capture cost still
2.00 GB (matches the 1.99 GB from the pre-refactor bcg-slice commit
within noise; baseline on main is 2.68 GB). Server serves /generate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Oasis-Git added a commit to Oasis-Git/sglang that referenced this pull request Jun 11, 2026
The previous ShapeKey refactor commit changed the decode + EAGLE
_make_graph_key methods to construct ShapeKey(size=bs * num_tokens_per_bs).
That subtly changed the dict-key identity vs the original
_make_graph_key(bs, stream_idx, variant_label) which keyed on `bs`
alone. Revert to ShapeKey(size=bs) so the cuda-graph key identity is
identical to pre-refactor behavior.

BCG output-buffer sharing (sgl-project#27659) is unaffected: prefill constructs
ShapeKey(size=num_tokens) which IS the leading dim of the captured
output, and decode BCG is not the default code path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Oasis-Git added a commit to Oasis-Git/sglang that referenced this pull request Jun 11, 2026
Strip the # PR sgl-project#27659 ... explanatory blocks from BreakableCudaGraph-
Backend (capture iteration order, copy-into-shared-buffer mechanics)
and the tombstone left where the old _make_graph_key helper used to
live. Simplify shape_key.py's module docstring to its one-line subject.

The code is self-explanatory; the historical context belongs in the
commit / PR description, not in source where it rots.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants