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
283 lines
10 KiB
Python
283 lines
10 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from http import HTTPStatus
|
|
from typing import (
|
|
TYPE_CHECKING,
|
|
Any,
|
|
Callable,
|
|
List,
|
|
Optional,
|
|
Union,
|
|
)
|
|
|
|
import zmq
|
|
from torch.distributed import barrier
|
|
|
|
from sglang.srt.disaggregation.utils import prepare_abort
|
|
from sglang.srt.managers.io_struct import (
|
|
BatchTokenizedEmbeddingReqInput,
|
|
BatchTokenizedGenerateReqInput,
|
|
TokenizedEmbeddingReqInput,
|
|
TokenizedGenerateReqInput,
|
|
sock_recv,
|
|
)
|
|
from sglang.srt.managers.mm_utils import (
|
|
has_shm_features,
|
|
unwrap_shm_features,
|
|
)
|
|
from sglang.srt.utils import (
|
|
broadcast_pyobj,
|
|
point_to_point_pyobj,
|
|
)
|
|
from sglang.srt.utils.nvtx_utils import scheduler_nvtx_method
|
|
|
|
if TYPE_CHECKING:
|
|
from sglang.srt.configs.model_config import ModelConfig
|
|
from sglang.srt.distributed.parallel_state_wrapper import ParallelState
|
|
from sglang.srt.server_args import ServerArgs
|
|
from sglang.test.scripted_runtime.scheduler_hook import ScriptedSchedulerHook
|
|
from sglang.test.scripted_runtime.tokenizer_recv_proxy import (
|
|
ScriptedTokenizerRecvProxy,
|
|
)
|
|
|
|
|
|
@dataclass(kw_only=True, slots=True, frozen=True)
|
|
class SchedulerRequestReceiver:
|
|
recv_from_tokenizer: Union[zmq.Socket, ScriptedTokenizerRecvProxy]
|
|
recv_from_rpc: Optional[zmq.Socket]
|
|
recv_skipper: Any
|
|
input_blocker: Any
|
|
mm_receiver: Any
|
|
ps: ParallelState
|
|
tp_group: Any
|
|
tp_cpu_group: Any
|
|
attn_tp_group: Any
|
|
attn_tp_cpu_group: Any
|
|
attn_cp_group: Any
|
|
attn_cp_cpu_group: Any
|
|
world_group: Any
|
|
server_args: ServerArgs
|
|
model_config: ModelConfig
|
|
max_recv_per_poll: int
|
|
stream_output: Callable[..., None]
|
|
get_last_forward_mode: Callable[[], Any]
|
|
scripted_scheduler_hook: Optional[ScriptedSchedulerHook] = None
|
|
|
|
def recv_limit_reached(self, num_recv_reqs: int) -> bool:
|
|
if self.max_recv_per_poll < 0:
|
|
return False
|
|
return num_recv_reqs >= self.max_recv_per_poll
|
|
|
|
@scheduler_nvtx_method("scheduler.recv_requests")
|
|
def recv_requests(
|
|
self,
|
|
) -> List[Union[TokenizedGenerateReqInput, TokenizedEmbeddingReqInput, Any]]:
|
|
"""Receive results at tp_rank = 0 and broadcast it to all other TP ranks."""
|
|
|
|
if self.scripted_scheduler_hook is not None:
|
|
self.scripted_scheduler_hook.step()
|
|
|
|
if self.recv_skipper is not None:
|
|
if not self.recv_skipper.handle(self.get_last_forward_mode()):
|
|
return []
|
|
|
|
recv_reqs = self._pull_raw_reqs()
|
|
|
|
if self.input_blocker is not None:
|
|
recv_reqs = self.input_blocker.handle(recv_reqs)
|
|
|
|
recv_reqs = self._broadcast_reqs_across_ranks(recv_reqs)
|
|
|
|
if self.ps.pp_rank == 0:
|
|
self.unwrap_pickle_wrapper(recv_reqs)
|
|
|
|
recv_reqs = self._apply_mm_receiver(recv_reqs)
|
|
|
|
self._finalize_shm_features(recv_reqs)
|
|
|
|
return recv_reqs
|
|
|
|
def _pull_raw_reqs(self) -> Optional[List]:
|
|
if self.ps.pp_rank == 0:
|
|
if self.ps.attn_tp_rank == 0 and self.ps.attn_cp_rank == 0:
|
|
recv_reqs = []
|
|
|
|
while True:
|
|
try:
|
|
if self.recv_limit_reached(len(recv_reqs)):
|
|
break
|
|
recv_req = sock_recv(self.recv_from_tokenizer, zmq.NOBLOCK)
|
|
except zmq.ZMQError:
|
|
break
|
|
recv_reqs.append(recv_req)
|
|
|
|
while True:
|
|
try:
|
|
if self.recv_limit_reached(len(recv_reqs)):
|
|
break
|
|
recv_rpc = sock_recv(self.recv_from_rpc, zmq.NOBLOCK)
|
|
except zmq.ZMQError:
|
|
break
|
|
recv_reqs.append(recv_rpc)
|
|
else:
|
|
recv_reqs = None
|
|
else:
|
|
if self.ps.attn_tp_rank == 0 and self.ps.attn_cp_rank == 0:
|
|
dp_offset = (
|
|
self.ps.attn_dp_rank * self.ps.attn_cp_size * self.ps.attn_tp_size
|
|
)
|
|
recv_reqs = point_to_point_pyobj(
|
|
[],
|
|
self.ps.pp_rank * self.ps.tp_size + dp_offset,
|
|
self.world_group.cpu_group,
|
|
(self.ps.pp_rank - 1) * self.ps.tp_size + dp_offset,
|
|
self.ps.pp_rank * self.ps.tp_size + dp_offset,
|
|
)
|
|
else:
|
|
recv_reqs = None
|
|
return recv_reqs
|
|
|
|
def _broadcast_reqs_across_ranks(self, recv_reqs: Optional[List]) -> List:
|
|
if self.server_args.enable_dp_attention:
|
|
if self.ps.attn_tp_rank == 0 and self.ps.attn_cp_rank == 0:
|
|
work_reqs, control_reqs = self._split_work_and_control_reqs(recv_reqs)
|
|
else:
|
|
work_reqs = None
|
|
control_reqs = None
|
|
|
|
if self.ps.attn_tp_size != 1:
|
|
work_reqs = broadcast_pyobj(
|
|
work_reqs,
|
|
self.attn_tp_group.rank,
|
|
self.attn_tp_cpu_group,
|
|
src=self.attn_tp_group.ranks[0],
|
|
)
|
|
|
|
if self.ps.attn_cp_size != 1:
|
|
work_reqs = broadcast_pyobj(
|
|
work_reqs,
|
|
self.attn_cp_group.rank,
|
|
self.attn_cp_cpu_group,
|
|
src=self.attn_cp_group.ranks[0],
|
|
)
|
|
|
|
# When dp_attention_local_control_broadcast is enabled, each DP
|
|
# group leader already receives control messages from the DP
|
|
# controller, so we broadcast within attn_tp_group + attn_cp_group
|
|
# instead of the full tp_group. This avoids an expensive
|
|
# all-ranks gloo sync.
|
|
_local_ctrl = self.server_args.enable_dp_attention_local_control_broadcast
|
|
if _local_ctrl:
|
|
if self.ps.attn_tp_size != 1:
|
|
control_reqs = broadcast_pyobj(
|
|
control_reqs,
|
|
self.attn_tp_group.rank,
|
|
self.attn_tp_cpu_group,
|
|
src=self.attn_tp_group.ranks[0],
|
|
)
|
|
if self.ps.attn_cp_size != 1:
|
|
control_reqs = broadcast_pyobj(
|
|
control_reqs,
|
|
self.attn_cp_group.rank,
|
|
self.attn_cp_cpu_group,
|
|
src=self.attn_cp_group.ranks[0],
|
|
)
|
|
elif self.ps.tp_size != 1:
|
|
control_reqs = broadcast_pyobj(
|
|
control_reqs,
|
|
self.tp_group.rank,
|
|
self.tp_cpu_group,
|
|
src=self.tp_group.ranks[0],
|
|
)
|
|
recv_reqs = work_reqs + control_reqs
|
|
elif self.ps.tp_size != 1:
|
|
recv_reqs = broadcast_pyobj(
|
|
recv_reqs,
|
|
self.tp_group.rank,
|
|
self.tp_cpu_group,
|
|
src=self.tp_group.ranks[0],
|
|
)
|
|
return recv_reqs
|
|
|
|
def unwrap_pickle_wrapper(self, recv_reqs: Optional[List]) -> None:
|
|
if not recv_reqs:
|
|
return
|
|
|
|
for req in recv_reqs:
|
|
if isinstance(req, (TokenizedGenerateReqInput, TokenizedEmbeddingReqInput)):
|
|
req.unwrap_pickle_fields()
|
|
elif isinstance(
|
|
req, (BatchTokenizedGenerateReqInput, BatchTokenizedEmbeddingReqInput)
|
|
):
|
|
for sub_req in req:
|
|
sub_req.unwrap_pickle_fields()
|
|
|
|
def _apply_mm_receiver(self, recv_reqs: List) -> List:
|
|
# Process MM requests under EPD-disaggregation mode
|
|
if (
|
|
self.ps.pp_rank == 0
|
|
and self.server_args.language_only
|
|
and self.server_args.encoder_transfer_backend
|
|
in ["zmq_to_scheduler", "mooncake"]
|
|
):
|
|
recv_reqs, abort_reqs = self.mm_receiver.process_waiting_requests(recv_reqs)
|
|
for req, error_msg, error_code in abort_reqs:
|
|
status_code = (
|
|
HTTPStatus.BAD_REQUEST
|
|
if error_code == 400
|
|
else HTTPStatus.INTERNAL_SERVER_ERROR
|
|
)
|
|
prepare_abort(req, error_msg, status_code=status_code)
|
|
self.stream_output([req], req.return_logprob)
|
|
return recv_reqs
|
|
|
|
def _finalize_shm_features(self, recv_reqs: Optional[List]) -> None:
|
|
# Unwrap shared memory features AFTER all broadcasts complete,
|
|
# so that ShmPointerMMData metadata (not full tensor data) is what
|
|
# gets serialized during broadcast_pyobj.
|
|
if recv_reqs:
|
|
if self.model_config.is_multimodal and has_shm_features(recv_reqs):
|
|
# The broadcast source returns with its original objects while
|
|
# peer ranks may still be unpickling ShmPointerMMData
|
|
# (-> shm_open). Synchronize the same CPU groups that carried
|
|
# SHM-backed work requests before materialize() unlinks them.
|
|
if self.server_args.enable_dp_attention:
|
|
if self.ps.attn_tp_size > 1:
|
|
barrier(group=self.attn_tp_cpu_group)
|
|
if self.ps.attn_cp_size > 1:
|
|
barrier(group=self.attn_cp_cpu_group)
|
|
elif self.ps.tp_size > 1:
|
|
barrier(group=self.tp_cpu_group)
|
|
for req in recv_reqs:
|
|
unwrap_shm_features(req)
|
|
|
|
def _split_work_and_control_reqs(self, recv_reqs: List):
|
|
work_reqs = [
|
|
req
|
|
for req in recv_reqs
|
|
if isinstance(
|
|
req,
|
|
(
|
|
TokenizedGenerateReqInput,
|
|
TokenizedEmbeddingReqInput,
|
|
BatchTokenizedGenerateReqInput,
|
|
BatchTokenizedEmbeddingReqInput,
|
|
),
|
|
)
|
|
]
|
|
control_reqs = [
|
|
req
|
|
for req in recv_reqs
|
|
if not isinstance(
|
|
req,
|
|
(
|
|
TokenizedGenerateReqInput,
|
|
TokenizedEmbeddingReqInput,
|
|
BatchTokenizedGenerateReqInput,
|
|
BatchTokenizedEmbeddingReqInput,
|
|
),
|
|
)
|
|
]
|
|
return work_reqs, control_reqs
|