94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
242 lines
9.8 KiB
Python
242 lines
9.8 KiB
Python
from types import SimpleNamespace
|
|
from typing import TYPE_CHECKING, Callable, List
|
|
|
|
from sglang.srt.batch_overlap import two_batch_overlap
|
|
from sglang.srt.layers.attention.base_attn_backend import AttentionBackend
|
|
|
|
if TYPE_CHECKING:
|
|
from sglang.srt.model_executor.forward_batch_info import ForwardBatch
|
|
|
|
|
|
class TboAttnBackend(AttentionBackend):
|
|
def __init__(self, primary: AttentionBackend, children: List[AttentionBackend]):
|
|
super().__init__()
|
|
self.primary = primary
|
|
self.children = children
|
|
# Dispatcher aliases the primary's pool refs so get_attn_backend()
|
|
# reads through TboAttnBackend resolve to the underlying pool.
|
|
self.token_to_kv_pool = primary.token_to_kv_pool
|
|
self.req_to_token_pool = primary.req_to_token_pool
|
|
|
|
@classmethod
|
|
def init_new(cls, creator: Callable[[], AttentionBackend]):
|
|
return cls(
|
|
primary=creator(),
|
|
children=[creator() for _ in range(2)],
|
|
)
|
|
|
|
def _children_use_cuda_graph(self) -> bool:
|
|
"""Whether the TBO child backends participate in CUDA-graph capture/replay.
|
|
|
|
Some models only run TBO in eager prefill and keep their graph-captured
|
|
modes (decode / target-verify) NON-TBO on the primary backend. For those,
|
|
the children must NOT be driven through the cuda-graph paths: doing so
|
|
rebuilds their per-step metadata on every replay even though the captured
|
|
graph never uses them. For DeepSeek-V4 that metadata build (compressor /
|
|
indexer) leaks ROCm HSA resources across the 2 children -> eventual
|
|
HSA_STATUS_ERROR_OUT_OF_RESOURCES. Eager prefill TBO (init_forward_metadata)
|
|
is unaffected; only the *_graph paths are gated.
|
|
"""
|
|
return getattr(self.primary, "tbo_supports_cuda_graph", True)
|
|
|
|
def init_forward_metadata_out_graph(
|
|
self,
|
|
forward_batch: "ForwardBatch",
|
|
in_capture: bool = False,
|
|
):
|
|
self.primary.init_forward_metadata_out_graph(
|
|
forward_batch=forward_batch, in_capture=in_capture
|
|
)
|
|
if not self._children_use_cuda_graph():
|
|
return
|
|
tbo_children = getattr(forward_batch, "tbo_children", None)
|
|
if tbo_children is not None:
|
|
for child, forward_batch_child in zip(
|
|
self.children, tbo_children, strict=True
|
|
):
|
|
if forward_batch_child.batch_size > 0:
|
|
child.init_forward_metadata_out_graph(
|
|
forward_batch=forward_batch_child, in_capture=in_capture
|
|
)
|
|
return
|
|
if in_capture:
|
|
return
|
|
# Replay path: build_replay_fb_view returns a SimpleNamespace and
|
|
# tbo_plugin.replay_prepare does not call prepare_raw, so split the
|
|
# padded buffers here using the same indices the eager path would.
|
|
self._dispatch_children_from_replay_view(forward_batch)
|
|
|
|
def _dispatch_children_from_replay_view(self, fb_view) -> None:
|
|
bs = fb_view.batch_size
|
|
forward_mode = fb_view.forward_mode
|
|
spec_info = fb_view.spec_info
|
|
token_num_per_seq = two_batch_overlap.get_token_num_per_seq(
|
|
forward_mode=forward_mode, spec_info=spec_info
|
|
)
|
|
num_tokens = bs * token_num_per_seq
|
|
(
|
|
tbo_split_seq_index,
|
|
tbo_split_token_index,
|
|
) = two_batch_overlap.compute_split_indices_for_cuda_graph_replay(
|
|
forward_mode=forward_mode,
|
|
cuda_graph_num_tokens=num_tokens,
|
|
spec_info=spec_info,
|
|
)
|
|
bs_left = tbo_split_seq_index
|
|
bs_right = bs - bs_left
|
|
for child, child_bs, seq_slice, tok_slice in (
|
|
(
|
|
self.children[0],
|
|
bs_left,
|
|
slice(None, tbo_split_seq_index),
|
|
slice(None, tbo_split_token_index),
|
|
),
|
|
(
|
|
self.children[1],
|
|
bs_right,
|
|
slice(tbo_split_seq_index, None),
|
|
slice(tbo_split_token_index, None),
|
|
),
|
|
):
|
|
if child_bs == 0:
|
|
continue
|
|
child_fb_view = _build_tbo_child_replay_fb_view(
|
|
fb_view,
|
|
child_bs=child_bs,
|
|
seq_slice=seq_slice,
|
|
tok_slice=tok_slice,
|
|
token_num_per_seq=token_num_per_seq,
|
|
)
|
|
child.init_forward_metadata_out_graph(
|
|
forward_batch=child_fb_view, in_capture=False
|
|
)
|
|
|
|
def init_forward_metadata_in_graph(self, forward_batch: "ForwardBatch"):
|
|
self.primary.init_forward_metadata_in_graph(forward_batch=forward_batch)
|
|
if not self._children_use_cuda_graph():
|
|
return
|
|
tbo_children = getattr(forward_batch, "tbo_children", None)
|
|
if tbo_children is not None:
|
|
for child, forward_batch_child in zip(
|
|
self.children, tbo_children, strict=True
|
|
):
|
|
if forward_batch_child.batch_size > 0:
|
|
child.init_forward_metadata_in_graph(
|
|
forward_batch=forward_batch_child
|
|
)
|
|
|
|
def init_forward_metadata(self, forward_batch: "ForwardBatch"):
|
|
self.primary.init_forward_metadata(forward_batch=forward_batch)
|
|
if forward_batch.tbo_children is not None:
|
|
for child, forward_batch_child in zip(
|
|
self.children, forward_batch.tbo_children, strict=True
|
|
):
|
|
if forward_batch_child.batch_size > 0:
|
|
child.init_forward_metadata(forward_batch=forward_batch_child)
|
|
|
|
def init_cuda_graph_state(self, max_bs: int, max_num_tokens: int):
|
|
self.primary.init_cuda_graph_state(max_bs=max_bs, max_num_tokens=max_num_tokens)
|
|
if not self._children_use_cuda_graph():
|
|
return
|
|
for item in self.children:
|
|
# TODO for children, maybe can provide *smaller* max_bs to optimize
|
|
item.init_cuda_graph_state(max_bs=max_bs, max_num_tokens=max_num_tokens)
|
|
|
|
def on_after_cuda_graph_warmup(self):
|
|
self.primary.on_after_cuda_graph_warmup()
|
|
if not self._children_use_cuda_graph():
|
|
return
|
|
for child in self.children:
|
|
child.on_after_cuda_graph_warmup()
|
|
|
|
def get_cuda_graph_seq_len_fill_value(self):
|
|
ans = self.primary.get_cuda_graph_seq_len_fill_value()
|
|
if not self._children_use_cuda_graph():
|
|
return ans
|
|
for child in self.children:
|
|
assert ans == child.get_cuda_graph_seq_len_fill_value()
|
|
return ans
|
|
|
|
def forward(self, *args, **kwargs):
|
|
return self.primary.forward(*args, **kwargs)
|
|
|
|
def forward_extend(self, *args, **kwargs):
|
|
return self.primary.forward_extend(*args, **kwargs)
|
|
|
|
def forward_decode(self, *args, **kwargs):
|
|
return self.primary.forward_decode(*args, **kwargs)
|
|
|
|
def get_indexer_metadata(self, layer_id: int, forward_batch: "ForwardBatch"):
|
|
return self.primary.get_indexer_metadata(layer_id, forward_batch)
|
|
|
|
def __getattr__(self, name):
|
|
# Delegate backend-specific attributes/methods not explicitly wrapped
|
|
# above (e.g. DSV4's get_unified_swa_loc / get_swa_out_cache_loc, which
|
|
# the model calls directly via get_attn_backend()) to the primary
|
|
# full-batch backend. Inside TBO the per-child backend is resolved
|
|
# directly from the forward context, so this path only serves the
|
|
# non-overlapped forward (warmup / decode / TBO-ineligible batches).
|
|
# NOTE: __getattr__ runs only when normal lookup fails; guard `primary`
|
|
# to avoid infinite recursion before __init__ sets it.
|
|
if name == "primary":
|
|
raise AttributeError(name)
|
|
return getattr(self.primary, name)
|
|
|
|
|
|
def _build_tbo_child_replay_fb_view(
|
|
fb_view,
|
|
*,
|
|
child_bs: int,
|
|
seq_slice: slice,
|
|
tok_slice: slice,
|
|
token_num_per_seq: int,
|
|
) -> SimpleNamespace:
|
|
"""Slice a parent replay fb_view into a per-child view.
|
|
|
|
Mirrors the legacy ``_init_forward_metadata_cuda_graph_split`` (deleted
|
|
along with the cuda_graph variants) for the new
|
|
``init_forward_metadata_out_graph(fb_view)`` contract: padded
|
|
capture-time buffers are sliced per child, spec_info is split, and
|
|
seq_lens_sum is recomputed from the sliced ``seq_lens_cpu``.
|
|
"""
|
|
assert (
|
|
getattr(fb_view, "encoder_lens", None) is None
|
|
), "TBO replay split does not support encoder_lens yet"
|
|
spec_info = getattr(fb_view, "spec_info", None)
|
|
if spec_info is not None:
|
|
start_seq = seq_slice.start or 0
|
|
end_seq = seq_slice.stop if seq_slice.stop is not None else start_seq + child_bs
|
|
child_spec_info = two_batch_overlap.split_spec_info(
|
|
spec_info=spec_info,
|
|
start_seq_index=start_seq,
|
|
end_seq_index=end_seq,
|
|
start_token_index=start_seq * token_num_per_seq,
|
|
end_token_index=end_seq * token_num_per_seq,
|
|
)
|
|
else:
|
|
child_spec_info = None
|
|
child_seq_lens_cpu = fb_view.seq_lens_cpu[seq_slice]
|
|
parent_input_ids = getattr(fb_view, "input_ids", None)
|
|
parent_out_cache_loc = getattr(fb_view, "out_cache_loc", None)
|
|
return SimpleNamespace(
|
|
batch_size=child_bs,
|
|
forward_mode=fb_view.forward_mode,
|
|
actual_forward_mode=getattr(
|
|
fb_view, "actual_forward_mode", fb_view.forward_mode
|
|
),
|
|
input_ids=(
|
|
parent_input_ids[tok_slice] if parent_input_ids is not None else None
|
|
),
|
|
req_pool_indices=fb_view.req_pool_indices[seq_slice],
|
|
seq_lens=fb_view.seq_lens[seq_slice],
|
|
seq_lens_sum=int(child_seq_lens_cpu.sum()),
|
|
seq_lens_cpu=child_seq_lens_cpu,
|
|
encoder_lens=None,
|
|
out_cache_loc=(
|
|
parent_out_cache_loc[tok_slice]
|
|
if parent_out_cache_loc is not None
|
|
else None
|
|
),
|
|
spec_info=child_spec_info,
|
|
)
|