Hint users when wrongly execute it with partial ranks in dumper (#19014)

This commit is contained in:
fzyzcjy
2026-02-20 12:25:54 +08:00
committed by GitHub
parent b41d412c3d
commit fc1500adc6
2 changed files with 116 additions and 8 deletions

View File

@@ -57,6 +57,7 @@ class _Dumper:
partial_name: Optional[str] = None,
enable_http_server: bool = True,
cleanup_previous: bool = False,
collective_timeout: int = 60,
):
# Config
self._enable = enable
@@ -68,6 +69,7 @@ class _Dumper:
self._enable_grad = enable_grad
self._enable_model_value = enable_model_value
self._enable_model_grad = enable_model_grad
self._collective_timeout = collective_timeout
# States
self._partial_name = partial_name
@@ -96,6 +98,7 @@ class _Dumper:
"SGLANG_ENABLE_DUMPER_HTTP_SERVER", "1"
),
cleanup_previous=get_bool_env_var("SGLANG_DUMPER_CLEANUP_PREVIOUS", "0"),
collective_timeout=60,
)
def on_forward_pass_start(self):
@@ -119,11 +122,13 @@ class _Dumper:
if self._http_server_handled:
return
self._http_server_handled = True
_start_maybe_http_server(self)
_start_maybe_http_server(self, timeout_seconds=self._collective_timeout)
def _ensure_partial_name(self):
if self._partial_name is None:
self._partial_name = _get_partial_name()
self._partial_name = _get_partial_name(
timeout_seconds=self._collective_timeout
)
print(f"[Dumper] Choose partial_name={self._partial_name}")
def set_ctx(self, **kwargs):
@@ -331,11 +336,37 @@ def _torch_save(value, path: str):
print(f"[Dumper] Observe error={e} when saving data, skip the tensor")
def _get_partial_name():
def _collective_with_timeout(fn, operation_name: str, timeout_seconds: int = 60):
completed = threading.Event()
def watchdog():
if not completed.wait(timeout=timeout_seconds):
print(
f"\n[Dumper] WARNING: '{operation_name}' has not completed after "
f"{timeout_seconds}s. This usually means not all ranks are "
f"participating in this collective operation.\n",
flush=True,
)
thread = threading.Thread(target=watchdog, daemon=True)
thread.start()
try:
return fn()
finally:
completed.set()
def _get_partial_name(timeout_seconds: int = 60):
rank = _get_rank()
object_list = [str(time.time()) if rank == 0 else None]
if dist.is_initialized():
dist.broadcast_object_list(object_list, device="cuda")
_collective_with_timeout(
lambda: dist.broadcast_object_list(object_list, device="cuda"),
operation_name="broadcast_object_list in _get_partial_name",
timeout_seconds=timeout_seconds,
)
return object_list[0]
@@ -494,14 +525,16 @@ def _collect_megatron_parallel_info():
# -------------------------------------- http control server ------------------------------------------
def _start_maybe_http_server(dumper):
def _start_maybe_http_server(dumper, timeout_seconds: int = 60):
http_port = get_int_env_var("SGLANG_DUMPER_SERVER_PORT", 40000)
zmq_base_port = get_int_env_var("SGLANG_DUMPER_ZMQ_BASE_PORT", 16800)
if http_port <= 0:
return
local_handler = _DumperRpcHandler(dumper)
rpc_handles = _create_zmq_rpc_handles(local_handler, base_port=zmq_base_port)
rpc_handles = _create_zmq_rpc_handles(
local_handler, base_port=zmq_base_port, timeout_seconds=timeout_seconds
)
if _get_rank() == 0:
handler_class = _make_dumper_http_handler(rpc_handles=rpc_handles)
@@ -549,7 +582,9 @@ class _DumperRpcHandler:
# -------------------------------------- zmq rpc ------------------------------------------
def _create_zmq_rpc_handles(handler, base_port: int) -> Optional[List["_ZmqRpcHandle"]]:
def _create_zmq_rpc_handles(
handler, base_port: int, timeout_seconds: int = 60
) -> Optional[List["_ZmqRpcHandle"]]:
import zmq
rank = _get_rank()
@@ -578,7 +613,11 @@ def _create_zmq_rpc_handles(handler, base_port: int) -> Optional[List["_ZmqRpcHa
if dist.is_initialized():
all_addresses = [None] * world_size
dist.all_gather_object(all_addresses, local_addr)
_collective_with_timeout(
lambda: dist.all_gather_object(all_addresses, local_addr),
operation_name="all_gather_object in _create_zmq_rpc_handles",
timeout_seconds=timeout_seconds,
)
else:
all_addresses = [local_addr]
print(f"[Dumper.ZmqRpc] rank={rank} all_addresses={all_addresses}")