Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:38:16 +08:00

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,
)