Clarify the meaning of cpu_group / entry_rank when dp + tp is enabled. (#16876)

This commit is contained in:
Liangsheng Yin
2026-01-11 13:04:43 +08:00
committed by GitHub
parent c0248d6f37
commit 09e2571e2e
5 changed files with 34 additions and 36 deletions
+1 -1
View File
@@ -603,7 +603,7 @@ class SchedulerDisaggregationPrefillMixin:
""" """
polls = poll_and_all_reduce( polls = poll_and_all_reduce(
[req.disagg_kv_sender for req in self.disagg_prefill_inflight_queue], [req.disagg_kv_sender for req in self.disagg_prefill_inflight_queue],
self.tp_worker.get_attention_tp_cpu_group(), self.attn_tp_cpu_group,
) )
transferred_rids: List[str] = [] transferred_rids: List[str] = []
+28 -21
View File
@@ -60,10 +60,14 @@ from sglang.srt.disaggregation.utils import (
prepare_abort, prepare_abort,
) )
from sglang.srt.distributed import get_pp_group, get_world_group from sglang.srt.distributed import get_pp_group, get_world_group
from sglang.srt.distributed.parallel_state import get_tp_group
from sglang.srt.dllm.config import DllmConfig from sglang.srt.dllm.config import DllmConfig
from sglang.srt.environ import envs from sglang.srt.environ import envs
from sglang.srt.eplb.expert_distribution import get_global_expert_distribution_recorder from sglang.srt.eplb.expert_distribution import get_global_expert_distribution_recorder
from sglang.srt.layers.dp_attention import compute_dp_attention_world_info from sglang.srt.layers.dp_attention import (
compute_dp_attention_world_info,
get_attention_tp_group,
)
from sglang.srt.layers.moe import initialize_moe_config from sglang.srt.layers.moe import initialize_moe_config
from sglang.srt.layers.quantization.fp8_utils import initialize_fp8_gemm_config from sglang.srt.layers.quantization.fp8_utils import initialize_fp8_gemm_config
from sglang.srt.managers.io_struct import ( from sglang.srt.managers.io_struct import (
@@ -546,25 +550,24 @@ class Scheduler(
self.max_running_requests // self.pp_size, 1 self.max_running_requests // self.pp_size, 1
) )
self.tp_group = self.tp_worker.get_tp_group() self.tp_group = get_tp_group()
self.tp_cpu_group = self.tp_group.cpu_group self.tp_cpu_group = self.tp_group.cpu_group
self.attn_tp_group = self.tp_worker.get_attention_tp_group() self.attn_tp_group = get_attention_tp_group()
self.attn_tp_cpu_group = self.tp_worker.get_attention_tp_cpu_group() self.attn_tp_cpu_group = self.attn_tp_group.cpu_group
self.pp_group = get_pp_group() self.pp_group = get_pp_group()
self.world_group = get_world_group() self.world_group = get_world_group()
# With DP attention enabled, the entry rank is attn_tp_rank==0; # NOTE: dp_tp_* are request/data-plane coordination groups (not tensor collectives).
# otherwise the entry rank is TP group local rank 0. # When DP attention is enabled, scope to the attention-TP group; otherwise use
# For #11910, use the CPU communication group to broadcast VLM Python objects, # the base TP group. Entry rank is the local rank 0 in that group.
# avoiding any coupling with CUDA streams/devices. # Use the CPU (gloo) group to broadcast VLM Python objects and avoid CUDA
if self.server_args.enable_dp_attention: # stream/device coupling (#11910).
self.cpu_group = self.attn_tp_cpu_group self.dp_tp_group = (
self.entry_rank = self.attn_tp_group.first_rank self.attn_tp_group
self.is_entry_rank = self.attn_tp_rank == 0 if self.server_args.enable_dp_attention
else: else self.tp_group
self.cpu_group = self.tp_cpu_group )
self.entry_rank = self.tp_group.first_rank self.dp_tp_cpu_group = self.dp_tp_group.cpu_group
self.is_entry_rank = self.tp_group.rank_in_group == 0
self.pad_input_ids_func = self.tp_worker.get_pad_input_ids_func() self.pad_input_ids_func = self.tp_worker.get_pad_input_ids_func()
set_random_seed(self.random_seed) set_random_seed(self.random_seed)
@@ -1358,10 +1361,10 @@ class Scheduler(
if ( if (
torch.distributed.is_available() torch.distributed.is_available()
and torch.distributed.is_initialized() and torch.distributed.is_initialized()
and self.cpu_group is not None and self.dp_tp_cpu_group is not None
): ):
group_world_size = torch.distributed.get_world_size( group_world_size = torch.distributed.get_world_size(
group=self.cpu_group group=self.dp_tp_cpu_group
) )
except Exception as e: except Exception as e:
logger.warning( logger.warning(
@@ -1374,14 +1377,16 @@ class Scheduler(
# Since the Scheduler is single-threaded, any large CPU cost will impact # Since the Scheduler is single-threaded, any large CPU cost will impact
# handling of other messages. For example, CPU hits 99.9% can significantly # handling of other messages. For example, CPU hits 99.9% can significantly
# increase the CUDA kernel launch time. # increase the CUDA kernel launch time.
if self.is_entry_rank: if self.dp_tp_group.rank_in_group == 0:
# Only the entry rank materializes once from dict. # Only the entry rank materializes once from dict.
image_inputs = MultimodalInputs.from_dict(raw_mm_inputs) image_inputs = MultimodalInputs.from_dict(raw_mm_inputs)
# Broadcast to other TP ranks (use src=0 within the group). # Broadcast to other TP ranks (use src=0 within the group).
if group_world_size > 1: if group_world_size > 1:
obj_list = [image_inputs] obj_list = [image_inputs]
torch.distributed.broadcast_object_list( torch.distributed.broadcast_object_list(
obj_list, src=self.entry_rank, group=self.cpu_group obj_list,
src=self.dp_tp_group.first_rank,
group=self.dp_tp_cpu_group,
) )
image_inputs = obj_list[0] image_inputs = obj_list[0]
else: else:
@@ -1389,7 +1394,9 @@ class Scheduler(
if group_world_size > 1: if group_world_size > 1:
obj_list = [None] obj_list = [None]
torch.distributed.broadcast_object_list( torch.distributed.broadcast_object_list(
obj_list, src=self.entry_rank, group=self.cpu_group obj_list,
src=self.dp_tp_group.first_rank,
group=self.dp_tp_cpu_group,
) )
image_inputs = obj_list[0] image_inputs = obj_list[0]
else: else:
@@ -1079,7 +1079,7 @@ class SchedulerPPMixin:
""" """
polls = poll_and_all_reduce( polls = poll_and_all_reduce(
[req.disagg_kv_sender if is_send else req.kv_receiver for req in req_queue], [req.disagg_kv_sender if is_send else req.kv_receiver for req in req_queue],
self.tp_worker.get_attention_tp_cpu_group(), self.attn_tp_cpu_group,
) )
rids: List = [] rids: List = []
for poll_statuses in poll_statuses_group: for poll_statuses in poll_statuses_group:
@@ -39,7 +39,7 @@ class SchedulerProfilerMixin:
if envs.SGLANG_PROFILE_V2.get(): if envs.SGLANG_PROFILE_V2.get():
self._profile_manager = ProfileManager( self._profile_manager = ProfileManager(
tp_rank=self.tp_rank, tp_rank=self.tp_rank,
cpu_group=self.cpu_group, cpu_group=self.dp_tp_cpu_group,
gpu_id=self.gpu_id, gpu_id=self.gpu_id,
) )
return return
@@ -180,7 +180,7 @@ class SchedulerProfilerMixin:
schema.writeSchema(connection) schema.writeSchema(connection)
connection.commit() connection.commit()
del connection del connection
torch.distributed.barrier(self.cpu_group) torch.distributed.barrier(self.dp_tp_cpu_group)
self.rpd_profiler = rpdTracerControl() self.rpd_profiler = rpdTracerControl()
self.rpd_profiler.setPythonTrace(True) self.rpd_profiler.setPythonTrace(True)
@@ -291,14 +291,14 @@ class SchedulerProfilerMixin:
self.torch_profiler.export_chrome_trace( self.torch_profiler.export_chrome_trace(
os.path.join(self.torch_profiler_output_dir, filename) os.path.join(self.torch_profiler_output_dir, filename)
) )
torch.distributed.barrier(self.cpu_group) torch.distributed.barrier(self.dp_tp_cpu_group)
if self.rpd_profiler is not None: if self.rpd_profiler is not None:
self.rpd_profiler.rangePop() self.rpd_profiler.rangePop()
self.rpd_profiler.stop() self.rpd_profiler.stop()
self.rpd_profiler.flush() self.rpd_profiler.flush()
torch.distributed.barrier(self.cpu_group) torch.distributed.barrier(self.dp_tp_cpu_group)
if self.tp_rank == 0: if self.tp_rank == 0:
from sglang.srt.utils.rpd_utils import rpd_to_chrome_trace from sglang.srt.utils.rpd_utils import rpd_to_chrome_trace
-9
View File
@@ -83,15 +83,6 @@ class BaseTpWorker(ABC):
def get_pad_input_ids_func(self): def get_pad_input_ids_func(self):
return getattr(self.model_runner.model, "pad_input_ids", None) return getattr(self.model_runner.model, "pad_input_ids", None)
def get_tp_group(self):
return self.model_runner.tp_group
def get_attention_tp_group(self):
return self.model_runner.attention_tp_group
def get_attention_tp_cpu_group(self):
return getattr(self.model_runner.attention_tp_group, "cpu_group", None)
def get_memory_pool(self): def get_memory_pool(self):
return ( return (
self.model_runner.req_to_token_pool, self.model_runner.req_to_token_pool,