[rust-server] Use node-local HTTP ports for DP attention (#34430)

Signed-off-by: Sage Ahrac <sagiahrak@gmail.com>
This commit is contained in:
Sage
2026-09-10 02:22:44 +08:00
committed by GitHub
parent 7b791c9534
commit 8733da8cf4
3 changed files with 144 additions and 9 deletions
+34 -4
View File
@@ -1169,11 +1169,16 @@ class Engine(EngineScoreMixin, EngineBase):
weight_cache_daemon_procs,
)
launch_dummy_health_check_server(
get_serving().host,
get_serving().port,
get_observability().enable_metrics,
# A node-local Rust listener owns the health endpoints when present.
rust_server_owns_base_port = (
envs.SGLANG_RUST_SERVER.get() and node_hosts_rust_server()
)
if not rust_server_owns_base_port:
launch_dummy_health_check_server(
get_serving().host,
get_serving().port,
get_observability().enable_metrics,
)
scheduler_init_result.block_until_scheduler_exits()
return (
@@ -1870,6 +1875,31 @@ def _calculate_rank_ranges(
return pp_rank_range, tp_rank_range, pp_size_per_node, tp_size_per_node
def node_hosts_rust_server() -> bool:
"""Whether this node contains a Rust listener rank, assuming Rust mode."""
parallel = get_parallel()
pp_rank_range, tp_rank_range, _, _ = _calculate_rank_ranges(
parallel.nnodes,
parallel.pp_size,
parallel.tp_size,
parallel.node_rank,
)
if 0 not in pp_rank_range:
return False
if get_exec().moe.is_ep_scale_joiner:
# Scale joiners launch the full local TP group, including its first rank.
return True
# Each attention DP group hosts a listener on its first rank (CP=TP=0).
ranks_per_dp_group = parallel.attn_tp_size * parallel.attn_cp_size
for tp_rank in tp_rank_range:
rank_within_dp_group = tp_rank % ranks_per_dp_group
if rank_within_dp_group == 0:
return True
return False
def _compute_parallelism_ranks(tp_rank: int) -> Tuple[int, int, int]:
"""Compute attention-CP, MoE-DP, and MoE-EP ranks for a TP rank.
+14 -5
View File
@@ -23,7 +23,7 @@ from sglang.srt.managers.utils import (
MsgpackDecodeError,
msgpack_decode_explained,
)
from sglang.srt.runtime_context import get_mm, get_serving
from sglang.srt.runtime_context import get_exec, get_mm, get_parallel, get_serving
from sglang.srt.rust_server.config import _build_server_args, _partition_cores
from sglang.srt.rust_server.multimodal import (
RUST_MM_FAMILIES,
@@ -79,10 +79,19 @@ class RustServer:
os.environ.setdefault("TOKENIZERS_PARALLELISM", "false")
server_args = scheduler.server_args
# Per-DP-rank HTTP port with client load balancing. `None` when DP is off,
# so the rank is not conflated with rank 0 of a one-rank group.
# Preserve the DP startup log; ports use node-local offsets.
dp_rank = scheduler.ps.attn_dp_rank if scheduler.ps.dp_size > 1 else None
listen_port = get_serving().port + (dp_rank or 0)
if get_exec().moe.is_ep_scale_joiner:
# The joining TP group is entirely local to this node.
tp_size_per_node = scheduler.ps.tp_size
else:
nnodes_per_pp_rank = max(get_parallel().nnodes // scheduler.ps.pp_size, 1)
tp_size_per_node = scheduler.ps.tp_size // nnodes_per_pp_rank
dp_group_width = scheduler.ps.attn_tp_size * scheduler.ps.attn_cp_size
# Count DP leaders within this node's TP range. The first leader must
# use the base port even when a DP group spans multiple nodes.
local_dp_rank = (scheduler.ps.tp_rank % tp_size_per_node) // dp_group_width
listen_port = get_serving().port + local_dp_rank
listen_addr = NetworkAddress(get_serving().host, listen_port).to_host_port_str()
launch_cores, server_cores = _partition_cores(
@@ -97,7 +106,7 @@ class RustServer:
_build_server_args(scheduler),
# None -> run unpinned; the list carries the pinning decision.
cores=server_cores,
port_offset=dp_rank,
port_offset=local_dp_rank,
)
# Multimodal models must have a Rust pipeline — there is no Python