VoxCPM-BACKUP_2 / scripts /ddp_probe.py
Jiwon-Kang's picture
Add files using upload-large-folder tool
bcc1595 verified
Raw
History Blame Contribute Delete
3.26 kB
#!/usr/bin/env python3
"""torchrun/NCCL 멀티 노드 bootstrap만 확인하는 최소 DDP probe."""
from __future__ import annotations
import argparse
import datetime as dt
import os
import socket
import sys
import time
import torch
import torch.distributed as dist
def _print(message: str) -> None:
print(f"[ddp_probe][pid={os.getpid()}] {message}", flush=True)
def _env_line() -> str:
keys = [
"RANK",
"LOCAL_RANK",
"WORLD_SIZE",
"MASTER_ADDR",
"MASTER_PORT",
"CUDA_VISIBLE_DEVICES",
"NCCL_SOCKET_IFNAME",
]
return " ".join(f"{key}={os.environ.get(key, '<unset>')}" for key in keys)
def main() -> None:
parser = argparse.ArgumentParser(description="Minimal torch.distributed bootstrap probe.")
parser.add_argument("--backend", default="", help="Distributed backend. Default: nccl when CUDA exists, else gloo.")
parser.add_argument("--timeout-sec", type=int, default=300, help="init_process_group timeout in seconds.")
parser.add_argument("--sleep-sec", type=int, default=0, help="Sleep after barrier for nvidia-smi inspection.")
args = parser.parse_args()
local_rank = int(os.environ.get("LOCAL_RANK", "0"))
backend = args.backend or ("nccl" if torch.cuda.is_available() else "gloo")
_print(f"host={socket.gethostname()} fqdn={socket.getfqdn()} python={sys.executable}")
_print(f"env {_env_line()}")
_print(
f"torch={torch.__version__} cuda_available={torch.cuda.is_available()} "
f"cuda_device_count={torch.cuda.device_count()} backend={backend}"
)
if torch.cuda.is_available():
if local_rank >= torch.cuda.device_count():
raise RuntimeError(
f"LOCAL_RANK={local_rank} but torch.cuda.device_count()={torch.cuda.device_count()}"
)
torch.cuda.set_device(local_rank)
_print(
f"after set_device local_rank={local_rank} "
f"current_device={torch.cuda.current_device()} name={torch.cuda.get_device_name(local_rank)}"
)
elif backend == "nccl":
raise RuntimeError("NCCL backend requires CUDA, but torch.cuda.is_available() is false.")
_print("before init_process_group")
dist.init_process_group(
backend=backend,
init_method="env://",
timeout=dt.timedelta(seconds=args.timeout_sec),
)
rank = dist.get_rank()
world = dist.get_world_size()
_print(f"after init_process_group rank={rank} world={world} backend={dist.get_backend()}")
device = torch.device("cuda", local_rank) if backend == "nccl" else torch.device("cpu")
value = torch.tensor([rank + 1], dtype=torch.float32, device=device)
_print(f"before all_reduce value={value.item()} device={value.device}")
dist.all_reduce(value, op=dist.ReduceOp.SUM)
expected = world * (world + 1) / 2
_print(f"after all_reduce value={value.item()} expected={expected}")
_print("before barrier")
dist.barrier()
_print("after barrier")
if args.sleep_sec > 0:
_print(f"sleeping {args.sleep_sec}s before destroy_process_group")
time.sleep(args.sleep_sec)
dist.destroy_process_group()
_print("destroyed process group; OK")
if __name__ == "__main__":
main()