196 lines
6.0 KiB
Markdown
196 lines
6.0 KiB
Markdown
# 数据并行与ZeRO
|
||
|
||
## 数据并行回顾
|
||
|
||
数据并行(Data Parallelism,DP)是最基础的分布式训练范式:
|
||
|
||
1. **模型复制**:每张GPU持有完整模型副本
|
||
2. **数据分片**:不同GPU处理不同数据batch
|
||
3. **梯度同步**:每轮迭代后对各GPU的梯度做AllReduce同步
|
||
4. **参数更新**:所有GPU使用相同的更新后参数继续下一轮
|
||
|
||
```
|
||
GPU 0: [模型副本] + [数据分片0] → [本地梯度] → AllReduce → [更新后模型]
|
||
GPU 1: [模型副本] + [数据分片1] → [本地梯度] → AllReduce → [更新后模型]
|
||
...
|
||
```
|
||
|
||
### 朴素数据并行的局限
|
||
|
||
- **显存浪费**:每张GPU保存完整模型、激活值、优化器状态,显存占用极大
|
||
- **通信瓶颈**:梯度AllReduce通信量 = 模型参数量,对大模型不现实
|
||
- **扩展性差**:模型参数量超过单卡显存时无法运行
|
||
|
||
## ZeRO(Zero Redundancy Optimizer)
|
||
|
||
ZeRO是微软DeepSpeed团队提出的显存优化技术,通过分片(sharding)消除数据并行中的显存冗余。
|
||
|
||
### Stage 1:优化器状态分片(Optimizer State Sharding)
|
||
|
||
**原理**:将Adam优化器的状态(动量、方差)在数据并行进程间分片,每个GPU只保存 1/N 的优化器状态。
|
||
|
||
```
|
||
优化器状态总量: 2 * 参数总量(动量 + 方差)
|
||
Stage 1后: 每GPU只保存 2 * 参数总量 / N
|
||
```
|
||
|
||
**通信开销**:
|
||
- 通信量:与标准数据并行相同(梯度AllReduce)
|
||
- 额外通信:参数分片 scatter/gather(可选)
|
||
|
||
**收益**:约4倍显存降低(假设N=8,则显存降至1/4)
|
||
|
||
### Stage 2:梯度分片(Gradient Sharding)
|
||
|
||
**原理**:在Stage 1基础上,进一步将梯度分片存储。
|
||
|
||
```
|
||
标准DP: 每GPU保存完整梯度 → AllReduce → 每GPU有完整梯度 → 参数更新
|
||
Stage 2: 每GPU保存 1/N 梯度 → 需要时 AllReduce(分片通信)
|
||
```
|
||
|
||
**实现机制**:
|
||
1. 反向传播时本地计算梯度
|
||
2. 执行Reduce-Scatter,每个GPU获得其他GPU数据的部分和
|
||
3. 本地更新对应参数分片
|
||
4. 下次前向传播前执行All-Gather重建完整梯度(可选)
|
||
|
||
**通信模式**:
|
||
- 通信量:与Stage 1相同,但通信模式不同(从AllReduce变为Reduce-Scatter + AllGather)
|
||
- 可与通信计算重叠进一步优化
|
||
|
||
**收益**:约8倍显存降低(结合Stage 1)
|
||
|
||
### Stage 3:参数分片(Parameter Sharding)
|
||
|
||
**原理**:将模型参数也分片存储,每个GPU只保存 1/N 的参数。
|
||
|
||
```
|
||
完整分片流程:
|
||
前向/反向: 动态 All-Gather 获取所需参数分片 → 计算 → 丢弃非必要分片
|
||
```
|
||
|
||
**实现机制**:
|
||
1. 前向传播时:参数分片本地计算,需要邻 GPU 参数时通过All-Gather获取
|
||
2. 反向传播时:梯度分片本地更新,触发Reduce-Scatter同步
|
||
3. 每轮迭代结束后参数分片自动同步
|
||
|
||
**通信开销**:
|
||
- 每层前向/反向都需要 All-Gather(获取参数)和 Reduce-Scatter(同步梯度)
|
||
- 通信量显著增加,但换取极大显存节省
|
||
|
||
**收益**:理论上显存降低与GPU数成线性关系
|
||
|
||
### ZeRO 通信量分析
|
||
|
||
| Stage | 通信量(相比DP) | 显存收益 |
|
||
|-------|-----------------|---------|
|
||
| Stage 1 | 1x (相同) | 4x |
|
||
| Stage 2 | 1x (相同) | 8x |
|
||
| Stage 3 | ~2x (AllGather+ReduceScatter) | O(N) |
|
||
|
||
### ZeRO-DP 与标准DP对比
|
||
|
||
```
|
||
标准DP:
|
||
每GPU内存占用 = 参数 + 梯度 + 优化器状态 + 激活值
|
||
≈ 模型大小 × (1 + 2 + 4) ≈ 7× 模型大小(16位存储)
|
||
|
||
ZeRO-3:
|
||
每GPU内存占用 ≈ (参数 + 梯度 + 优化器状态) / N + 激活值
|
||
≈ 模型大小 / N + 激活值
|
||
```
|
||
|
||
## DeepSpeed实现
|
||
|
||
### 配置文件示例
|
||
|
||
```python
|
||
{
|
||
"zero_optimization": {
|
||
"stage": 3,
|
||
"offload_optimizer": {
|
||
"device": "cpu",
|
||
"pin_memory": true
|
||
},
|
||
"offload_param": {
|
||
"device": "cpu",
|
||
"pin_memory": true
|
||
},
|
||
"overlap_comm": true,
|
||
"contiguous_gradients": true,
|
||
"reduce_bucket_size": 1e8,
|
||
"stage3_prefetch_bucket_size": 1e9,
|
||
"stage3_param_persistence_threshold": 1e5
|
||
},
|
||
"bf16": {
|
||
"enabled": true
|
||
}
|
||
}
|
||
```
|
||
|
||
### 核心API
|
||
|
||
```python
|
||
from deepspeed import DeepSpeedConfig, initialize
|
||
model, optimizer, _, _ = initialize(
|
||
args=args,
|
||
model=model,
|
||
model_parameters=model.parameters(),
|
||
config=deepspeed_config
|
||
)
|
||
```
|
||
|
||
### ZeRO-3 关键技术
|
||
|
||
1. **分片通信与计算重叠**:利用CUDA stream在计算时通信
|
||
2. **Gradient Accumulation**:梯度累积避免流水线空闲
|
||
3. **Weight Gradients Partitioning**:参数梯度自动分片
|
||
4. **Partition Communication Group**:自定义通信域
|
||
|
||
### ZeRO-Stage 3与PipeDream的结合
|
||
|
||
DeepSpeed支持将ZeRO与流水线并行结合:
|
||
|
||
```python
|
||
{
|
||
"zero_optimization": {"stage": 3},
|
||
"pipeline": {"stages": 4}
|
||
}
|
||
```
|
||
|
||
每个pipeline stage内部使用ZeRO-3分片,进一步降低单卡显存。
|
||
|
||
### Offload技术
|
||
|
||
DeepSpeed支持将部分数据卸载到CPU或NVMe:
|
||
|
||
- **ZeRO-Offload**:优化器状态卸载到CPU,配合Stage 2
|
||
- **ZeRO-Infinity**:参数和优化器状态卸载到NVMe,支持超大规模模型
|
||
|
||
### 性能调优
|
||
|
||
1. **通信瓶颈**:TP/PP机器与DP机器分离,避免跨域通信
|
||
2. **通信域配置**:优化 NCCL 组配置
|
||
3. **Mixed Precision**:BF16训练减少通信量
|
||
4. **Async IO**:参数卸载异步化避免阻塞
|
||
|
||
## 与其他并行策略的关系
|
||
|
||
| 策略 | 维度 | 分片对象 |
|
||
|------|------|---------|
|
||
| 张量并行 | 层内 | 参数/激活切分 |
|
||
| 流水线并行 | 层间 | 模型层分Stage |
|
||
| 数据并行 | batch | 梯度/参数同步 |
|
||
| ZeRO | 数据并行维度 | 参数/梯度/优化器状态分片 |
|
||
|
||
三者可组合:TP=8, PP=4, ZeRO-3 + DP = N/(8*4)
|
||
|
||
## 框架对比
|
||
|
||
| 特性 | DeepSpeed ZeRO | Megatron-FSDP | PyTorch FSDP |
|
||
|------|---------------|---------------|--------------|
|
||
| 分片方式 | 优化器状态+梯度+参数 | 参数+梯度+优化器状态 | 参数+梯度 |
|
||
| Offload | CPU/NVMe | CPU | CPU |
|
||
| 通信优化 | Overlap + Partition | Async | Overlap |
|
||
| 易用性 | 高(配置驱动) | 中 | 中 | |