λLLM Wiki

Data Parallelism

数据并行(Data Parallelism, DP) 是最基础的分布式训练策略:在多个 GPU 上各放一份完整的模型副本,将训练数据切成不同子集分发给各 GPU,每个 GPU 独立做前向和反向,最后通过 梯度全归约(gradient all-reduce) 同步梯度。

核心思路

  1. 每个 GPU(称为一个 rank)持有模型的完整拷贝
  2. 一个 mini-batch 被均匀切成 NN 份(NN 为 GPU 数),每个 rank 处理一份
  3. 前向和反向计算完全独立,无需通信
  4. 反向完成后,所有 rank 通过 all-reduce 对梯度取平均
  5. 各 rank 用相同的平均梯度更新参数,保证参数始终一致

通信只发生在梯度同步阶段,通信量与模型参数量成正比,与数据量无关。

存在的问题:显存瓶颈

朴素 DP 要求每个 GPU 都放得下完整的模型参数、梯度和优化器状态。当模型增大到数十亿参数时,单卡显存不足以容纳这些数据。

ZeRO 优化

ZeRO(Zero Redundancy Optimizer) 通过消除跨 rank 的冗余存储来缓解显存问题,分三个级别:

级别切分内容显存节省额外通信
ZeRO-1优化器状态约 4×少量
ZeRO-2优化器状态 + 梯度约 8×中等
ZeRO-3优化器状态 + 梯度 + 参数最大需要 all-gather 参数

ZeRO-3 的理念是”切分为了存储”——参数被分片存放,计算前临时通过 all-gather 聚合完整参数,计算后再释放。

FSDP:PyTorch 的 ZeRO 实现

FSDP(Fully Sharded Data Parallelism) 是 PyTorch 对 ZeRO-3 的原生实现,有两个版本:

  • FSDP1:把一个模块的所有参数压平成一个 FlatParameter,然后对这个大张量做切分。粒度粗,通信可能冗余(计算 W1W_1 时也要聚合 W2,W3,W4W_2, W_3, W_4)。
  • FSDP2:用 DTensor 对每个参数独立切分。粒度更细,按需通信,更容易与计算做 overlap,也支持 per-parameter 元数据管理和 native LoRA。

两者的关键区别:

维度FSDP1FSDP2
切分粒度模块级(FlatParameter)参数级(DTensor)
通信精度聚合整个模块的参数只聚合当前需要的参数
组合性较差可与 TP、PP 嵌套

DP 与 TP 的本质区别

  • DP 切分为了存储:每个 rank 存一份参数分片,计算前必须先 all-gather 出完整参数。
  • TP 切分为了计算:每个 rank 只存且只算参数的一部分,计算直接在分片上进行。

两者通常组合使用:节点内用 TP 切分大层,节点间用 FSDP2 做数据并行扩展。

相关页面

Comments