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
204 lines
6.8 KiB
Python
204 lines
6.8 KiB
Python
import inspect
|
|
import logging
|
|
import os
|
|
import sys
|
|
import types
|
|
from dataclasses import dataclass
|
|
from typing import Any, Callable, Optional, Union
|
|
|
|
import torch
|
|
|
|
from sglang.srt.compilation.compilation_config import CompilationConfig
|
|
from sglang.srt.model_executor.runner_backend_utils.tc_piecewise_cuda_graph import (
|
|
is_in_tc_piecewise_cuda_graph,
|
|
)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@dataclass
|
|
class IntermediateTensors:
|
|
"""For all pipeline stages except the last, we need to return the hidden
|
|
states and residuals to be sent to the next stage. This data structure
|
|
contains the hidden states and residuals for a request.
|
|
|
|
Each stage also needs to handle its own finished_sending and
|
|
finished_recving in case of kv transfer.
|
|
"""
|
|
|
|
tensors: dict[str, torch.Tensor]
|
|
# [req_ids]
|
|
finished_sending: Optional[set[str]] = None
|
|
finished_recving: Optional[set[str]] = None
|
|
|
|
def __init__(self, tensors):
|
|
# manually define this function, so that
|
|
# Dynamo knows `IntermediateTensors()` comes from this file.
|
|
# Otherwise, dataclass will generate this function by evaluating
|
|
# a string, and we will lose the information about the source file.
|
|
self.tensors = tensors
|
|
|
|
def __getitem__(self, key: Union[str, slice]):
|
|
if isinstance(key, str):
|
|
return self.tensors[key]
|
|
elif isinstance(key, slice):
|
|
return self.__class__({k: v[key] for k, v in self.tensors.items()})
|
|
|
|
def __setitem__(self, key: str, value: torch.Tensor):
|
|
self.tensors[key] = value
|
|
|
|
def items(self):
|
|
return self.tensors.items()
|
|
|
|
def __len__(self):
|
|
return len(self.tensors)
|
|
|
|
def __eq__(self, other: object):
|
|
return isinstance(other, self.__class__) and self
|
|
|
|
def __repr__(self) -> str:
|
|
return f"IntermediateTensors(tensors={self.tensors})"
|
|
|
|
|
|
def _normalize_dims(dims, ndim: int):
|
|
dims = [dims] if isinstance(dims, int) else list(dims)
|
|
return [d if d >= 0 else ndim + d for d in dims]
|
|
|
|
|
|
class _MaybeIntermediateTensors:
|
|
"""Duck-typed check to support your IntermediateTensors without importing."""
|
|
|
|
def __init__(self, obj):
|
|
self.is_intermediate = hasattr(obj, "tensors") and isinstance(
|
|
getattr(obj, "tensors"), dict
|
|
)
|
|
self.obj = obj
|
|
|
|
|
|
def _mark_dynamic_on_value(val, dims):
|
|
if isinstance(val, torch.Tensor):
|
|
torch._dynamo.maybe_mark_dynamic(val, _normalize_dims(dims, val.ndim))
|
|
else:
|
|
mit = _MaybeIntermediateTensors(val)
|
|
if mit.is_intermediate:
|
|
for t in mit.obj.tensors.values():
|
|
torch._dynamo.maybe_mark_dynamic(t, _normalize_dims(dims, t.ndim))
|
|
# else: ignore (None or non-tensor)
|
|
|
|
|
|
def _infer_dynamic_arg_dims_from_annotations(forward_fn):
|
|
sig = inspect.signature(forward_fn)
|
|
dyn = {}
|
|
for name, p in sig.parameters.items():
|
|
ann = p.annotation
|
|
# Accept torch.Tensor / Optional[torch.Tensor] / your IntermediateTensors types by name
|
|
if (
|
|
ann is torch.Tensor
|
|
or getattr(getattr(ann, "__args__", [None])[0], "__name__", "") == "Tensor"
|
|
):
|
|
dyn[name] = 0
|
|
elif getattr(ann, "__name__", "") in ("IntermediateTensors",) or any(
|
|
getattr(a, "__name__", "") == "IntermediateTensors"
|
|
for a in getattr(ann, "__args__", [])
|
|
):
|
|
dyn[name] = 0
|
|
elif ann == "torch.Tensor" or ann == "Optional[torch.Tensor]":
|
|
# For future import annotations (e.g. from __future__ import annotations), the annotation is a string
|
|
dyn[name] = 0
|
|
if not dyn:
|
|
raise ValueError("No dynamic dims inferred; pass dynamic_arg_dims explicitly.")
|
|
return dyn
|
|
|
|
|
|
def install_torch_compiled(
|
|
module: torch.nn.Module,
|
|
*,
|
|
dynamic_arg_dims: dict[str, Union[int, list[int]]] | None = None,
|
|
backend_factory: Optional[Callable[[torch.fx.GraphModule, list], Callable]] = None,
|
|
compile_config: CompilationConfig = None,
|
|
fullgraph: bool = True,
|
|
graph_pool: Any = None,
|
|
):
|
|
unbound_fwd = module.__class__.forward
|
|
if not callable(unbound_fwd):
|
|
raise TypeError("module.__class__.forward must be callable")
|
|
original_code = unbound_fwd.__code__
|
|
|
|
dyn_map = dynamic_arg_dims or _infer_dynamic_arg_dims_from_annotations(unbound_fwd)
|
|
|
|
if backend_factory is None:
|
|
from sglang.srt.compilation.backend import SGLangBackend
|
|
|
|
backend_factory = lambda gm, ex: SGLangBackend(compile_config, graph_pool)(
|
|
gm, ex
|
|
)
|
|
|
|
compiled_codes: list[type(original_code)] = []
|
|
state = {"compiled": False, "compiled_callable": None}
|
|
|
|
def bytecode_hook(old_code, new_code):
|
|
if old_code is not original_code:
|
|
return
|
|
frame = sys._getframe()
|
|
while frame and frame.f_back:
|
|
frame = frame.f_back
|
|
if (
|
|
frame.f_code.co_name == "_compile"
|
|
and os.path.basename(frame.f_code.co_filename) == "convert_frame.py"
|
|
):
|
|
break
|
|
try:
|
|
dynamo_frame = frame.f_locals["frame"]
|
|
except Exception:
|
|
return
|
|
if dynamo_frame.f_code is not old_code:
|
|
return
|
|
if dynamo_frame.f_locals.get("self") is not module:
|
|
return
|
|
compiled_codes.append(new_code)
|
|
|
|
torch._dynamo.convert_frame.register_bytecode_hook(bytecode_hook)
|
|
|
|
def _ensure_compiled(self, *args, **kwargs):
|
|
"""Compile on first use (with flag ON)."""
|
|
if state["compiled"]:
|
|
return
|
|
# Mark dynamic dims only when we are about to compile
|
|
sig = inspect.signature(unbound_fwd)
|
|
ba = sig.bind(self, *args, **kwargs)
|
|
ba.apply_defaults()
|
|
for name, dims in (dyn_map or {}).items():
|
|
if name in ba.arguments:
|
|
val = ba.arguments[name]
|
|
if val is not None:
|
|
_mark_dynamic_on_value(val, dims)
|
|
|
|
# Avoid cross-instance cache reuse
|
|
torch._dynamo.eval_frame.remove_from_cache(unbound_fwd.__code__)
|
|
|
|
bound = types.MethodType(unbound_fwd, self)
|
|
compiled_callable = torch.compile(
|
|
bound, fullgraph=fullgraph, backend=backend_factory
|
|
)
|
|
|
|
# Trigger Dynamo so bytecode hook can capture
|
|
compiled_callable(*args, **kwargs)
|
|
|
|
state["compiled"] = True
|
|
state["compiled_callable"] = compiled_callable
|
|
|
|
def trampoline(self, *args, **kwargs):
|
|
use_compiled = is_in_tc_piecewise_cuda_graph()
|
|
if use_compiled:
|
|
if not state["compiled"]:
|
|
_ensure_compiled(self, *args, **kwargs)
|
|
|
|
compiled_callable = state["compiled_callable"]
|
|
return compiled_callable(*args, **kwargs)
|
|
else:
|
|
# Explicitly run the original uncompiled forward
|
|
return unbound_fwd(self, *args, **kwargs)
|
|
|
|
module.forward = types.MethodType(trampoline, module)
|
|
return module
|