跳转至

二十一:分布式训练:DDP、DP 与 FSDP自测题答案

来源:http://mp.weixin.qq.com/s?__biz=MzYyNTk3Njg1NA==&mid=2247484206&idx=1&sn=7258c5ca7b597aa14f1819fbd4763826&chksm=f01eb057c769394178704b8db9fdbdc5418e736d06278fab4f093b809d5e202d9b6884e1fa4c#rd

参考资料

  • PyTorch DistributedDataParallel 文档:https://pytorch.org/docs/stable/generated/torch.nn.parallel.DistributedDataParallel.html

  • PyTorch Distributed Overview:https://pytorch.org/tutorials/beginner/dist_overview.html

  • PyTorch FSDP 文档:https: //pytorch.org/docs/stable/fsdp.html

  • DDP 实战视频:https://www.bilibili.com/video/BV1wS421w7ug/

  • 对比 DP、DDP 和 FSDP:https://zhuanlan.zhihu.com/p/650002268

评分标准

  • 合格:能说明 DDP 是每卡一进程、完整模型副本、数据分片、梯度 all-reduce。

  • 良好:能解释 rank/world_size、DistributedSampler、global batch、no_sync、checkpoint 和 unused parameter。

  • 优秀:能系统比较 DP/DDP/FSDP/ZeRO,并能给出性能排错和多机启动方案。

一、分布式训练基础

1. 为什么需要分布式训练?

为了解决单卡速度慢、显存不足、数据量大和模型规模大的问题。多卡可以提高吞吐,也可以通过分片训练更大模型。

2. 数据并行、张量并行、流水线并行分别拆分什么?

数据并行拆 batch;张量并行拆单层矩阵计算;流水线并行按网络层拆模型阶段。

3. DDP 属于哪类并行?它默认是否切分模型参数?

DDP 是数据并行。默认不切分参数,每个 rank 都有完整模型副本。

4. 数据并行中 global batch 如何计算?

global_batch = per_device_batch * world_size * gradient_accumulation_steps

5. 数据并行为什么需要同步梯度?

每张卡看到不同数据,局部梯度不同。同步平均梯度后,各卡才能执行相同 optimizer step,保持参数一致。

6. 多卡训练为什么不一定线性加速?

存在梯度通信、dataloader、同步等待、负载不均和网络带宽瓶颈。

7. 通信带宽为什么会成为分布式训练瓶颈?

DDP 每步要同步梯度,模型越大梯度越大,跨机通信尤其容易成为瓶颈。

8. 单机多卡和多机多卡训练的主要差异是什么?

多机需要网络通信、master 地址端口、节点 rank、共享存储和更复杂的 NCCL 配置。

二、DP、DDP 与 FSDP 对比

9. PyTorch DataParallel 的基本工作方式是什么?

单进程多线程,把输入 scatter 到多卡,主卡 gather 输出并更新,其他卡负载较轻。

10. DataParallel 为什么通常不推荐用于生产训练?

主卡瓶颈明显,线程和 gather 开销大,多机支持差,通信计算重叠能力弱。

11. DDP 和 DataParallel 的核心区别是什么?

DDP 是多进程,每个进程管理一张 GPU,通过分布式通信同步梯度;DP 是单进程多线程。

12. DDP 为什么推荐一张 GPU 一个进程?

可以避免 GIL 和主卡瓶颈,充分利用 NCCL 通信,并使每个 GPU 独立执行。

13. DDP 每张卡是否保存完整模型?

是。DDP 每个 rank 保存完整参数、梯度和优化器状态。

14. DDP 能不能解决单卡放不下模型的问题?为什么?

不能。因为每卡仍有完整模型副本。单卡放不下要用 FSDP、ZeRO、tensor parallel 或 pipeline parallel。

15. FSDP 与 DDP 的核心区别是什么?

FSDP 分片参数、梯度和优化器状态;DDP 复制这些状态。

16. ZeRO 与 FSDP 的共同目标是什么?

减少每张卡上参数、梯度、优化器状态的冗余,从而训练更大模型。

17. 什么情况下优先选择 DDP?

模型能放进单卡,主要想提升吞吐,训练代码希望简单稳定时优先 DDP。

18. 什么情况下应考虑 FSDP 或 ZeRO?

模型、梯度或优化器状态单卡放不下,或显存压力成为主要瓶颈时。

三、DDP 核心概念

19. rank、local_rank、world_size 分别是什么?

rank 是全局进程编号,local_rank 是节点内 GPU 编号,world_size 是总进程数。

20. process group 是什么?

参与通信的一组进程。DDP 在 process group 内同步梯度。

21. NCCL 和 Gloo backend 有什么区别?

NCCL 主要面向 GPU 高性能通信;Gloo 支持 CPU/GPU 但 GPU 性能通常不如 NCCL。

22. 为什么 GPU 训练通常选择 NCCL?

NCCL 对 NVIDIA GPU、NVLink、InfiniBand 等通信路径优化更好。

23. torchrun --nproc_per_node=8 train.py 表示什么?

在当前节点启动 8 个训练进程,通常对应 8 张 GPU。

24. 多机 DDP 还需要配置哪些启动参数?

需要 nnodesnode_rankmaster_addrmaster_port,以及每节点进程数。

25. torch.cuda.set_device(local_rank) 为什么重要?

确保当前进程只使用对应 GPU,避免多个进程抢同一张卡。

26. DDP 包装模型前后 checkpoint key 可能有什么区别?

DDP 包装后原模型在 model.module,保存时常用 model.module.state_dict() 避免多一层 wrapper 前缀问题。

四、DDP 训练流程

27. 请描述 DDP 从初始化到训练一步的完整流程。

初始化 process group;设置 device;构建模型并 DDP 包装;用 DistributedSampler 切数据;本地 forward/backward;DDP all-reduce 梯度;各 rank 执行 optimizer step。

28. DDP 中每个 rank 的模型参数初始如何保持一致?

通常从同一 checkpoint 初始化,DDP 初始化也会广播参数确保一致。

29. forward 阶段 DDP 是否通信?

普通 DDP forward 通常不进行梯度同步通信;主要通信在 backward。

30. backward 阶段 DDP 何时通信?

梯度计算完成后,对对应 bucket 触发 all-reduce。

31. all-reduce 在 DDP 中做什么?

聚合所有 rank 的梯度并把结果分发回每个 rank。

32. 为什么 all-reduce 后每个 rank 的梯度相同?

all-reduce 的结果是所有 rank 梯度的和或平均,每个 rank 收到相同结果。

33. optimizer step 为什么每个 rank 都要执行?

每个 rank 都有完整模型副本,同步梯度相同,所以各自 step 后参数仍一致。

34. 如果只在 rank 0 执行 optimizer step 会怎样?

其他 rank 参数不会更新,下一步模型副本不一致,训练错误。

35. DDP bucket 的作用是什么?

把多个参数梯度分组通信,减少小通信次数,并支持通信与 backward 重叠。

36. DDP 如何实现通信和 backward 计算重叠?

某个 bucket 梯度就绪后立刻 all-reduce,同时 autograd 继续计算其他层梯度。

五、数据加载与 Batch

37. DistributedSampler 解决什么问题?

让不同 rank 读取不同数据分片,避免每张卡重复训练同一 batch。

38. 为什么使用 DistributedSampler 时通常要设置 shuffle=False?

shuffle 由 sampler 控制。DataLoader 再 shuffle 会和 sampler 逻辑冲突。

39. sampler.set_epoch(epoch) 的作用是什么?

让每个 epoch 使用不同随机种子 shuffle,避免每轮数据顺序相同。

40. 如果忘记 set_epoch 会有什么影响?

每个 epoch 的数据顺序可能重复,随机性不足,影响训练效果。

41. DDP 中每个 rank 的 dataloader 长度不一致可能导致什么问题?

某些 rank 先结束,其他 rank 还在等待通信,可能卡住或报错。

42. global batch 变大后学习率应如何考虑?

可尝试线性缩放学习率并增加 warmup,但需要验证收敛和泛化。

43. gradient accumulation 如何影响 global batch?

累积步数乘进 global batch。累积 4 步等价于 batch 放大 4 倍。

44. DDP 中 no_sync() 解决什么问题?

在梯度累积的中间步跳过梯度同步,减少通信开销。

45. loss 是 mean 时是否需要再除以 world_size?

通常不需要。DDP 已同步平均梯度,再除会让梯度过小。

46. 日志中的 loss 和 accuracy 应如何跨 rank 汇总?

使用 all-reduce 汇总 sum/count,再计算全局平均,而不是只看 rank 0。

六、混合精度、Unused Parameters 与 Checkpoint

47. DDP 可以和 AMP 一起使用吗?需要注意什么?

可以。所有 rank 的 AMP 配置要一致,FP16 注意 GradScaler,BF16 通常不需要 scaler。

48. BF16 和 FP16 在 DDP 混合精度中有什么差异?

BF16 动态范围更大,训练更稳;FP16 尾数更精细但更容易 overflow,需要 loss scaling。

49. 什么是 unused parameter 问题?

某些参数在一次 forward 中没有参与 loss,导致 DDP 等不到对应梯度。

50. find_unused_parameters=True 有什么作用和代价?

它遍历 autograd 图找未使用参数,避免卡住,但增加开销。

51. 动态图模型为什么更容易触发 unused parameter?

条件分支、MoE、部分任务头或 adapter 可能某步不走某些参数。

52. SyncBatchNorm 解决什么问题?

跨 rank 同步 BatchNorm 统计,避免每卡小 batch 统计不稳定。

53. LLM 中为什么通常不关心 SyncBatchNorm?

LLM 通常使用 LayerNorm/RMSNorm,而不是 BatchNorm。

54. DDP 保存 checkpoint 时为什么常用 model.module.state_dict()?

model 是 DDP wrapper,model.module 才是原始模型。

55. DDP 断点恢复应保存哪些状态?

模型、优化器、scheduler、scaler、epoch、global step、随机数状态和 sampler 相关状态。

56. 为什么多 rank 同时写同一个 checkpoint 路径可能出问题?

可能写冲突、文件损坏或重复 IO。通常只让 rank 0 写。

七、性能与排错

57. DDP 训练速度慢时应从哪些方面排查?

排查 dataloader、GPU 利用率、batch size、通信占比、网络带宽、bucket、CPU-GPU 同步和负载均衡。

58. dataloader 成为瓶颈有什么表现?

GPU 利用率周期性下降,等待数据时间长,增加 num_workers 或预取后吞吐提升。

59. NCCL timeout 可能有哪些原因?

网络不通、某 rank 崩溃、rank 配置错误、某 rank OOM、通信顺序不一致或 dataloader 卡住。

60. DDP 卡住可能有哪些非通信原因?

unused parameter、某个 rank 数据耗尽、异常未广播、死锁、不同 rank 控制流不一致。

61. 某个 rank OOM 为什么可能让其他 rank 也卡住?

OOM rank 退出或停在异常处,其他 rank 仍等待 all-reduce,最终 timeout。

62. 如何判断通信开销是否过高?

用 profiler 查看 all-reduce 时间占比,比较单卡/多卡 scaling efficiency,观察 NCCL 时间。

63. 为什么 batch size 太小会降低 DDP 效率?

计算量少,通信固定开销占比变高,GPU 不易饱和。

64. 多机 DDP 中 MASTER_ADDR 和 MASTER_PORT 有什么作用?

用于所有进程 rendezvous,建立分布式通信组。

65. NCCL 网络接口配置错误会导致什么问题?

可能走低速网卡、连接失败或 timeout。

66. 如何排查不同 rank 数据重复或数据遗漏?

打印/记录样本 id,检查 DistributedSampler、drop_last、seed、set_epoch 和 world_size。

八、综合设计

67. 请写出一个最小 DDP 训练脚本需要包含的关键步骤。

初始化 process group;读取 local_rank;设置 CUDA device;构建模型并 DDP 包装;使用 DistributedSampler;训练循环;保存 rank 0 checkpoint;销毁 process group。

68. 如何把单卡训练代码改造成 DDP?

加入 torchrun 启动、dist 初始化、local_rank device、DDP wrapper、DistributedSampler、跨 rank 指标汇总和 rank 0 checkpoint。

69. 如何设计一个 2 机 8 卡 DDP 训练启动方案?

每机 8 进程,nnodes=2,两机分别 node_rank=0/1,统一 master_addr/master_port,总 world_size=16。

70. 请完整比较 DP、DDP、FSDP、ZeRO 在并行对象、显存占用、通信方式、优缺点和适用场景上的差异。

DP 单进程多卡,简单但主卡瓶颈大。DDP 多进程数据并行,复制完整状态,通过 all-reduce 同步梯度,适合模型能单卡放下的高效训练。FSDP 分片参数、梯度和优化器状态,显存省但通信复杂。ZeRO 分 stage 分片 optimizer/gradient/parameter,适合大模型训练,常由 DeepSpeed 管理。

            预览时标签不可点




































<div class="