训练卡在 torch.distributed.init_process_group 是因 nccl 网络通信失败,主因是网卡选择错误或 master_addr/port 不通;应指定 nccl_socket_ifname、nccl_backend=tcp,显式使用 tcp:// 初始化,并检查连通性。

训练进程卡在 torch.distributed.init_process_group 不往下走
这是最典型的“挂起”现象,不是报错,而是所有 rank 停在初始化阶段,CPU 占用低、无日志输出。根本原因通常是网络通信没通——不是防火墙挡了端口,就是 NCCL 尝试用错误的网卡(比如选了虚拟机内网或 Docker bridge 网卡,而非真实物理网卡)。
实操建议:
- 先手动指定 NCCL 使用的网卡:
export NCCL_SOCKET_IFNAME=ens3f0(把ens3f0换成ip a里显示的、能跨节点 ping 通的物理网卡名) - 加环境变量强制 NCCL 走 TCP(绕过 IB/RoCE):
export NCCL_BACKEND=tcp,再试一次,看是否还卡 - 检查
MASTER_ADDR和MASTER_PORT是否被所有节点正确解析:在每个节点上执行ping -c 1 $MASTER_ADDR和nc -zv $MASTER_ADDR $MASTER_PORT - 别依赖默认的
init_method='env://',显式传参更可控:torch.distributed.init_process_group(backend='nccl', init_method='tcp://$MASTER_ADDR:$MASTER_PORT', rank=$RANK, world_size=$WORLD_SIZE)
ncclTimeout 错误或 GPU 显存暴涨后挂住
NCCL 在集合通信(如 allreduce)时等不到某个 rank 的数据,超时后可能静默卡死,或触发重试导致显存持续增长。常见于 IO 瓶颈:数据加载慢 → 某个 rank 的 forward 拖后腿 → 其他 rank 在 backward 阶段等它 → NCCL 同步阻塞。
实操建议:
- 用
nvidia-smi dmon -s u -d 1观察各 GPU 的 util%,如果某卡长期 - 把
DataLoader的num_workers设为 0 先跑通,排除子进程初始化问题;再逐步加到min(8, os.cpu_count()),避免 fork 太多进程压垮 IO - 确认磁盘类型:NVMe SSD 可以开
pin_memory=True+non_blocking=True;如果是 SATA 盘或网络文件系统(NFS/Ceph),关掉pin_memory,否则内存拷贝反而成瓶颈 - 加
torch.utils.data.DataLoader(..., timeout=60),让卡死的 worker 主动抛异常,别默默等
使用 torch.nn.parallel.DistributedDataParallel 后 loss 不降或梯度为 NaN
DDP 本身不改模型逻辑,但会自动做梯度同步。如果 loss 异常,往往不是 DDP 的锅,而是同步前的计算出了问题——比如某个 rank 上的 batch 数据损坏、label 越界、或者用了未同步的随机数种子。
实操建议:
- 在
DDP包裹前,对每个 rank 单独打印loss.item()和model.parameters().__next__().grad(非 None 且不全为 NaN),确认单卡行为一致 - 所有随机操作必须带 rank seed:
torch.manual_seed(42 + rank),np.random.seed(42 + rank),random.seed(42 + rank) - 别在 dataset
__getitem__里用time.time()或未设 seed 的random.choice,不同 rank 加载顺序可能不同,导致 batch 内容错位 - 检查 loss 函数输入:比如
nn.CrossEntropyLoss要求 target 是long类型,若某 rank 上 target 是float,会静默出 NaN,且 DDP 同步后全卡都崩
分布式训练吞吐远低于单卡 × GPU 数
线性加速比破 0.7 就该怀疑瓶颈在哪。NCCL 带宽打不满?GPU 计算被 IO 或 CPU 解码拖累?还是模型里有未并行的全局操作?
实操建议:
- 用
nccl-tests测裸 NCCL 带宽:./build/all_reduce_perf -b 8M -e 128M -f 2 -g 1,对比理论值(比如双路 IB 为 200+ GB/s),若实测 - 用
py-spy record -p $PID -o profile.svg抓训练中 Python 栈,重点看是否大量时间花在Dataset.__getitem__或PIL.Image.open上 - 检查是否误用
torch.cat/torch.stack在 GPU 上拼接跨 rank 数据——这会强制同步,改用all_gather+ CPU 拼接 - 小模型(FSDP 或
DeepSpeed Zero-2,但别为了省显存盲目上,它们引入新复杂度
网络和 IO 这两层,只要有一处没对齐(比如 RDMA 驱动版本不一致、NFS 客户端缓存策略不同、甚至不同节点的时钟偏差 > 1s),就可能让训练在某个边界 case 下突然卡住。调试时别跳步,从 ping 和 nc 开始,一层层往上摸。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











