因为ddp依赖已初始化的进程组,未调用torch.distributed.init_process_group就直接使用会报该错;必须用torchrun启动并确保各进程在模型封装前完成一致参数的初始化。

为什么直接用 torch.nn.parallel.DistributedDataParallel 会报错“Default process group is not initialized”
因为 DDP 不是开箱即用的封装,它依赖底层的进程组(process group)通信初始化。没调用 torch.distributed.init_process_group 就直接实例化 DDP,必然触发这个错误。
常见误操作包括:只在单卡脚本里加了 DDP(model),但没启动多进程、没设置 MASTER_ADDR/MASTER_PORT、也没调用初始化函数。
- 必须用
torch.distributed.launch或torchrun启动,不能直接python train.py -
init_process_group要在模型包装前调用,且所有 GPU 进程必须使用**完全一致**的参数(尤其是rank和world_size) - 推荐用
torchrun(PyTorch 1.9+),它自动分配rank和world_size,不用手动解析命令行参数
如何正确构造 DDP 模型并处理数据加载
DDP 本身不负责数据分片,得靠 DistributedSampler 配合 DataLoader 实现每张卡看到不同子集。漏掉这一步会导致所有卡训练同一份数据,等效于单卡重复计算。
关键点在于:DistributedSampler 的 shuffle 必须设为 True(训练时),且 DataLoader 的 shuffle 必须关掉——否则 sampler 失效。
- 初始化 sampler 时传入
num_replicas=world_size、rank=rank -
DataLoader的batch_size是**每卡**的 batch size,不是全局 batch size - 验证/测试阶段可不用
DistributedSampler,但要确保各卡评估的是同一份数据(比如用SequentialSampler或去掉 sampler)
# 示例片段(训练循环前) train_sampler = torch.utils.data.DistributedSampler(dataset, num_replicas=world_size, rank=rank, shuffle=True) train_loader = DataLoader(dataset, batch_size=32, sampler=train_sampler, num_workers=4) model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[local_rank])
训练过程中梯度同步和 loss 计算的常见陷阱
DDP 默认在 backward() 后自动同步梯度,但 loss 值默认是**每卡独立计算的**。如果直接打印或记录 loss.item(),你会看到每张卡输出不同数值,无法反映全局训练进度。
想得到平均 loss,必须显式做跨卡 reduce。别用 torch.mean() 对 list 操作——那只是 CPU 上的平均,不是分布式平均。
- 用
torch.distributed.all_reduce(loss, op=torch.distributed.ReduceOp.SUM),再除以world_size - 注意:
loss必须是 0 维 tensor 且在 GPU 上(如loss = loss.mean().cuda()) - 验证阶段若需准确指标(如 accuracy),也得 gather 所有卡的预测和标签再统一计算,不能各自算完取平均
为什么 torchrun 启动后某张卡卡住或报 “NCCL timeout”
NCCL 是 DDP 默认后端,超时通常意味着进程间通信失败,和网络、CUDA 环境、GPU 可见性强相关,和代码逻辑无关。
- 检查
CUDA_VISIBLE_DEVICES是否被意外覆盖(torchrun默认不接管它,需手动设) - 确认所有卡在同一台机器上(NCCL 默认不支持跨机,除非显式配置
NCCL_SOCKET_IFNAME和 IP) - 避免混用不同 CUDA 版本的 PyTorch 和驱动;升级到 PyTorch ≥ 2.0 + CUDA 11.8 后,NCCL 错误明显减少
- 临时调试可加环境变量:
export NCCL_ASYNC_ERROR_HANDLING=0和export NCCL_DEBUG=INFO查看具体哪步卡住
多卡训练真正难的不是写几行 DDP,而是让所有进程对齐状态、同步数据、收敛行为一致。哪怕一个 seed 没在每个进程里单独 set,或者一个 torch.no_grad() 块里做了未同步的 tensor 操作,都可能让结果不可复现或静默出错。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











