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
305 lines
9.9 KiB
Python
305 lines
9.9 KiB
Python
from __future__ import annotations
|
|
|
|
import bisect
|
|
from enum import Enum
|
|
from typing import List, Optional, Sequence, Tuple
|
|
|
|
import msgspec
|
|
import torch
|
|
|
|
from sglang.srt.environ import envs
|
|
|
|
|
|
class RaggedVerifyMode(str, Enum):
|
|
STATIC = "static"
|
|
CAP_ACCEPT = "cap-accept"
|
|
COMPACT = "compact"
|
|
|
|
|
|
def read_ragged_verify_mode() -> RaggedVerifyMode:
|
|
value = envs.SGLANG_RAGGED_VERIFY_MODE.get()
|
|
for mode in RaggedVerifyMode:
|
|
if value == mode.value:
|
|
return mode
|
|
raise ValueError(
|
|
f"invalid SGLANG_RAGGED_VERIFY_MODE={value!r}; expected one of "
|
|
f"{', '.join(repr(m.value) for m in RaggedVerifyMode)}"
|
|
)
|
|
|
|
|
|
def ragged_verify_compact_enabled() -> bool:
|
|
return read_ragged_verify_mode() == RaggedVerifyMode.COMPACT
|
|
|
|
|
|
def round_up_grid(total: int, grid: Sequence[int]) -> int:
|
|
if not grid:
|
|
raise ValueError("round_up_grid requires a non-empty grid")
|
|
if total > grid[-1]:
|
|
raise ValueError(
|
|
f"total {total} exceeds max grid tier {grid[-1]}; "
|
|
"the caller must reject this batch before selecting a graph tier"
|
|
)
|
|
index = bisect.bisect_left(grid, total)
|
|
return grid[index]
|
|
|
|
|
|
class RaggedVerifyLayout(msgspec.Struct, frozen=True):
|
|
verify_lens: torch.Tensor
|
|
graph_num_tokens: int
|
|
extend_start_loc: torch.Tensor
|
|
qo_indptr_device: torch.Tensor
|
|
verify_lens_cpu: Optional[list[int]] = None
|
|
total_verify_tokens: Optional[int] = None
|
|
qo_indptr_host: Optional[torch.Tensor] = None
|
|
kv_indptr_host: Optional[torch.Tensor] = None
|
|
kv_lens_host: Optional[torch.Tensor] = None
|
|
max_q_len: Optional[int] = None
|
|
max_kv_len: Optional[int] = None
|
|
|
|
def __post_init__(self) -> None:
|
|
if self.verify_lens_cpu is None:
|
|
return
|
|
if not self.verify_lens_cpu:
|
|
raise ValueError("RaggedVerifyLayout requires at least one request")
|
|
if min(self.verify_lens_cpu) < 1:
|
|
raise ValueError(
|
|
f"every request must verify the anchor (verify_len >= 1), got "
|
|
f"{self.verify_lens_cpu}"
|
|
)
|
|
if self.total_verify_tokens != sum(self.verify_lens_cpu):
|
|
raise ValueError(
|
|
f"total_verify_tokens {self.total_verify_tokens} != "
|
|
f"sum(verify_lens_cpu) {sum(self.verify_lens_cpu)}"
|
|
)
|
|
if not (self.total_verify_tokens <= self.graph_num_tokens):
|
|
raise ValueError(
|
|
f"total_verify_tokens {self.total_verify_tokens} exceeds "
|
|
f"graph_num_tokens {self.graph_num_tokens}"
|
|
)
|
|
|
|
@property
|
|
def bs(self) -> int:
|
|
return int(self.verify_lens.shape[0])
|
|
|
|
@classmethod
|
|
def _assemble_device(
|
|
cls,
|
|
*,
|
|
verify_lens: torch.Tensor,
|
|
graph_num_tokens: int,
|
|
verify_lens_cpu: Optional[list[int]] = None,
|
|
total_verify_tokens: Optional[int] = None,
|
|
) -> RaggedVerifyLayout:
|
|
from sglang.srt.speculative.ragged_verify_kernels import (
|
|
BuildQoIndptr,
|
|
)
|
|
|
|
verify_lens = verify_lens.to(torch.int32)
|
|
indptr = BuildQoIndptr.execute(verify_lens=verify_lens)
|
|
return cls(
|
|
verify_lens=verify_lens,
|
|
graph_num_tokens=graph_num_tokens,
|
|
extend_start_loc=indptr.extend_start_loc,
|
|
qo_indptr_device=indptr.qo_indptr,
|
|
verify_lens_cpu=verify_lens_cpu,
|
|
total_verify_tokens=total_verify_tokens,
|
|
)
|
|
|
|
@classmethod
|
|
def _assemble(
|
|
cls,
|
|
*,
|
|
verify_lens_cpu: list[int],
|
|
total_verify_tokens: int,
|
|
graph_num_tokens: int,
|
|
device: torch.device,
|
|
) -> RaggedVerifyLayout:
|
|
verify_lens = torch.tensor(verify_lens_cpu, dtype=torch.int32, device=device)
|
|
return cls._assemble_device(
|
|
verify_lens=verify_lens,
|
|
graph_num_tokens=graph_num_tokens,
|
|
verify_lens_cpu=verify_lens_cpu,
|
|
total_verify_tokens=total_verify_tokens,
|
|
)
|
|
|
|
@classmethod
|
|
def from_verify_lens_device(
|
|
cls,
|
|
*,
|
|
verify_lens: torch.Tensor,
|
|
graph_num_tokens: int,
|
|
) -> RaggedVerifyLayout:
|
|
return cls._assemble_device(
|
|
verify_lens=verify_lens, graph_num_tokens=graph_num_tokens
|
|
)
|
|
|
|
@classmethod
|
|
def from_verify_lens(
|
|
cls,
|
|
*,
|
|
verify_lens_cpu: Sequence[int],
|
|
device: torch.device,
|
|
grid: Sequence[int],
|
|
graph_num_tokens_floor: int = 0,
|
|
) -> RaggedVerifyLayout:
|
|
verify_lens_list = [int(v) for v in verify_lens_cpu]
|
|
total_verify_tokens = sum(verify_lens_list)
|
|
bucket_input = max(total_verify_tokens, graph_num_tokens_floor)
|
|
graph_num_tokens = round_up_grid(total=bucket_input, grid=grid)
|
|
|
|
return cls._assemble(
|
|
verify_lens_cpu=verify_lens_list,
|
|
total_verify_tokens=total_verify_tokens,
|
|
graph_num_tokens=graph_num_tokens,
|
|
device=device,
|
|
)
|
|
|
|
def padded_to_bucket(self, *, padded_bs: int) -> RaggedVerifyLayout:
|
|
from sglang.srt.speculative.ragged_verify_kernels import (
|
|
PaddedToBucket,
|
|
)
|
|
|
|
padded = PaddedToBucket.execute(
|
|
verify_lens=self.verify_lens,
|
|
graph_num_tokens=self.graph_num_tokens,
|
|
bs=self.bs,
|
|
padded_bs=padded_bs,
|
|
)
|
|
|
|
return RaggedVerifyLayout._assemble_device(
|
|
verify_lens=padded,
|
|
graph_num_tokens=self.graph_num_tokens,
|
|
total_verify_tokens=self.graph_num_tokens,
|
|
)
|
|
|
|
|
|
def build_capture_verify_lens(
|
|
*,
|
|
num_tokens: int,
|
|
num_slots: int,
|
|
num_draft_tokens: int,
|
|
) -> list[int]:
|
|
if num_slots < 1 or num_tokens < num_slots:
|
|
raise ValueError(
|
|
f"capture layout needs 1 <= num_slots <= num_tokens, got "
|
|
f"num_slots={num_slots}, num_tokens={num_tokens}"
|
|
)
|
|
if num_tokens > num_slots * num_draft_tokens:
|
|
raise ValueError(
|
|
f"capture layout cannot pack num_tokens={num_tokens} into "
|
|
f"{num_slots} rows of at most {num_draft_tokens} tokens"
|
|
)
|
|
base = num_tokens // num_slots
|
|
rem = num_tokens - base * num_slots
|
|
return [base + 1] * rem + [base] * (num_slots - rem)
|
|
|
|
|
|
def resolve_ragged_verify_layout(forward_batch) -> Optional[RaggedVerifyLayout]:
|
|
"""Layout riding the batch's spec input, or None. Tolerates the runner's
|
|
ad-hoc replay batch views, which may not carry spec_info at all."""
|
|
spec_info = getattr(forward_batch, "spec_info", None)
|
|
if spec_info is None:
|
|
return None
|
|
return spec_info.ragged_verify_layout
|
|
|
|
|
|
class RaggedTargetVerifyGeometry(msgspec.Struct):
|
|
cache_seqlens_int32: torch.Tensor
|
|
cu_seqlens_q: torch.Tensor
|
|
cu_seqlens_k: torch.Tensor
|
|
max_seq_len_q: Optional[int]
|
|
|
|
|
|
def build_ragged_target_verify_geometry(
|
|
*,
|
|
seq_lens: torch.Tensor,
|
|
layout: RaggedVerifyLayout,
|
|
) -> RaggedTargetVerifyGeometry:
|
|
cache_seqlens_int32 = (seq_lens + layout.verify_lens).to(torch.int32)
|
|
cu_seqlens_q = layout.qo_indptr_device.to(torch.int32)
|
|
cu_seqlens_k = torch.nn.functional.pad(
|
|
torch.cumsum(cache_seqlens_int32, dim=0, dtype=torch.int32), (1, 0)
|
|
)
|
|
max_seq_len_q = (
|
|
max(layout.verify_lens_cpu) if layout.verify_lens_cpu is not None else None
|
|
)
|
|
return RaggedTargetVerifyGeometry(
|
|
cache_seqlens_int32=cache_seqlens_int32,
|
|
cu_seqlens_q=cu_seqlens_q,
|
|
cu_seqlens_k=cu_seqlens_k,
|
|
max_seq_len_q=max_seq_len_q,
|
|
)
|
|
|
|
|
|
def compute_target_verify_graph_key(
|
|
*,
|
|
bs: int,
|
|
num_draft_tokens: int,
|
|
ragged_layout: Optional[RaggedVerifyLayout],
|
|
) -> Tuple[int, int]:
|
|
num_tokens_full_block = num_draft_tokens * bs
|
|
if ragged_layout is None:
|
|
return bs, num_tokens_full_block
|
|
graph_num_tokens = ragged_layout.graph_num_tokens
|
|
assert graph_num_tokens <= num_tokens_full_block, (
|
|
f"ragged verify graph_num_tokens={graph_num_tokens} exceeds full block "
|
|
f"num_draft*bs={num_tokens_full_block}"
|
|
)
|
|
total_verify_tokens = ragged_layout.total_verify_tokens
|
|
if total_verify_tokens is not None:
|
|
assert total_verify_tokens <= graph_num_tokens, (
|
|
f"ragged verify total_verify_tokens={total_verify_tokens} exceeds the "
|
|
f"round-up bucket graph_num_tokens={graph_num_tokens}"
|
|
)
|
|
return graph_num_tokens, graph_num_tokens
|
|
|
|
|
|
class VerifyExtendLengths(msgspec.Struct, frozen=True):
|
|
seq_lens_extended: torch.Tensor
|
|
seq_lens_cpu_extended: List[int]
|
|
extend_seq_lens_cpu: List[int]
|
|
num_tokens: int
|
|
extend_start_loc: Optional[torch.Tensor]
|
|
|
|
|
|
def compute_uniform_extend_lengths(
|
|
*,
|
|
seq_lens: torch.Tensor,
|
|
seq_lens_cpu: List[int],
|
|
extend_len: int,
|
|
) -> VerifyExtendLengths:
|
|
batch_size = len(seq_lens_cpu)
|
|
seq_lens_extended = seq_lens + extend_len
|
|
seq_lens_cpu_extended = [x + extend_len for x in seq_lens_cpu]
|
|
extend_seq_lens_cpu = [extend_len] * batch_size
|
|
num_tokens = extend_len * batch_size
|
|
return VerifyExtendLengths(
|
|
seq_lens_extended=seq_lens_extended,
|
|
seq_lens_cpu_extended=seq_lens_cpu_extended,
|
|
extend_seq_lens_cpu=extend_seq_lens_cpu,
|
|
num_tokens=num_tokens,
|
|
extend_start_loc=None,
|
|
)
|
|
|
|
|
|
def compute_ragged_extend_lengths(
|
|
*,
|
|
seq_lens: torch.Tensor,
|
|
seq_lens_cpu: List[int],
|
|
ragged_layout: RaggedVerifyLayout,
|
|
) -> VerifyExtendLengths:
|
|
extend_seq_lens_cpu = list(ragged_layout.verify_lens_cpu)
|
|
seq_lens_extended = seq_lens + ragged_layout.verify_lens
|
|
seq_lens_cpu_extended = [
|
|
raw + length for raw, length in zip(seq_lens_cpu, extend_seq_lens_cpu)
|
|
]
|
|
num_tokens = ragged_layout.total_verify_tokens
|
|
extend_start_loc = ragged_layout.extend_start_loc
|
|
return VerifyExtendLengths(
|
|
seq_lens_extended=seq_lens_extended,
|
|
seq_lens_cpu_extended=seq_lens_cpu_extended,
|
|
extend_seq_lens_cpu=extend_seq_lens_cpu,
|
|
num_tokens=num_tokens,
|
|
extend_start_loc=extend_start_loc,
|
|
)
|