From c0172aef6eabca1eb1a8ac9b359f57cd7a0490e8 Mon Sep 17 00:00:00 2001 From: Xinyu Zhang <60529799+xyuzh@users.noreply.github.com> Date: Thu, 16 Apr 2026 14:52:15 -0700 Subject: [PATCH] [Ray] Bind scheduler actors to GPU-local NUMA node (#22989) Co-authored-by: xyuzh --- python/sglang/srt/ray/scheduler_actor.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/python/sglang/srt/ray/scheduler_actor.py b/python/sglang/srt/ray/scheduler_actor.py index 68d9fc654..13f588ebb 100644 --- a/python/sglang/srt/ray/scheduler_actor.py +++ b/python/sglang/srt/ray/scheduler_actor.py @@ -50,7 +50,12 @@ class SchedulerActor: ): import dataclasses - from sglang.srt.managers.scheduler import Scheduler, configure_scheduler + from sglang.srt.environ import envs + from sglang.srt.managers.scheduler import Scheduler, configure_scheduler_process + from sglang.srt.utils.numa_utils import ( + get_numa_node_if_available, + numa_bind_to_node, + ) # Override dist_init_addr if provided (for multi-node) if dist_init_addr: @@ -72,8 +77,9 @@ class SchedulerActor: logger.info(f"[TP{tp_rank}] Using passed gpu_id: {gpu_id}") # Configure worker (logging, process title, etc.) - dp_rank = configure_scheduler( + dp_rank = configure_scheduler_process( server_args, + actual_gpu_id, tp_rank, attn_cp_rank, moe_dp_rank, @@ -82,6 +88,18 @@ class SchedulerActor: dp_rank, ) + # Ray actors can't use the numactl subprocess-wrapping approach + # (SGLANG_NUMA_BIND_V2's normal path), so bind in-process via libnuma. + # The V1 path inside configure_scheduler_process already handles + # SGLANG_NUMA_BIND_V2=False. + if envs.SGLANG_NUMA_BIND_V2.get(): + numa_node = get_numa_node_if_available(server_args, actual_gpu_id) + if numa_node is not None: + numa_bind_to_node(numa_node) + logger.info( + f"[TP{tp_rank}] Bound to NUMA node {numa_node} for GPU {actual_gpu_id}" + ) + # Create scheduler (loads model into GPU, initializes NCCL) self.scheduler = Scheduler( server_args=server_args,