📍 本文是「LLM进阶:从会用到底层精通」专题的第 7/10 篇 | 难度:高级 | 预计阅读:25min
学习目标
---
一、为什么单卡不够用
以 DeepSeek-V3 为例:671B 参数,FP16 精度下仅模型权重就需要 671 × 2 = 1342 GB(约 1.3TB)显存,还不包括优化器状态(Adam 额外 8~12 字节/参数)和激活值。而单张 H100 只有 80GB,差距超过 15 倍。
千亿级模型从诞生之初就是"分布式原住民"——必须跨卡甚至跨节点部署。
---
二、三种并行策略对比
2.1 FSDP / ZeRO-3:数据并行 + 显存分片
ZeRO(Zero Redundancy Optimizer)核心思想:不再让每张 GPU 持有完整副本,而是把优化器状态、梯度和参数均匀分片到所有 GPU 上。
ZeRO-3 核心操作:前向/反向计算前通过 allgather 收集所需参数分片,完成后立即释放。PyTorch FSDP 原理等价于 ZeRO-3。
2.2 TP(Tensor Parallelism):层内张量切分
TP 将单层权重矩阵沿行或列切分到多张 GPU。例如 MLP 矩阵 [hidden, intermediate] 切为 [hidden, intermediate/N] 分布到 N 张卡,通信仅发生在矩阵乘法前后(一次 allreduce 或 allgather)。
🛠️ 实战经验:TP 通信发生在每层的前向/反向中,要求 GPU 间超带宽(NVLink 900GB/s)。跨节点 TP 基本不可行。
2.3 PP(Pipeline Parallelism):层间流水线
PP 将模型按层切分,通过 micro-batch 填充流水线减少气泡(bubble)。GPipe 中 bubble 占比 (P-1)/M,1F1B 调度可进一步减少显存峰值。
2.4 三维并行
千卡级标准方案:TP(节点内 NVLink)× PP(跨节点)× DP(最外层扩展)。Megatron-LM、DeepSpeed 均原生支持。
策略对比
---
三、NCCL 通信拓扑:Ring vs Tree
Ring 拓扑
GPU 首尾相连成环,数据分 chunk 依次传递。完成一次 allreduce 需 2×(N-1) 步,每步传输 message/N 的数据量:
Tree 拓扑
二叉树层次结构,reduce 从叶到根汇聚,broadcast 从根到叶分发。需 2×log₂(N) 步,但每步传完整消息:
🛠️ 实战经验:NCCL 2.12+ 启用混合算法,小消息走 Ring、大消息走 Tree。遇到通信瓶颈时先用 nccl-tests 做基准测试。---
四、Checkpoint 与故障恢复
千卡训练中故障是常态。GPU 单卡 MTBF 在数月量级,但千卡集群每天就可能遇到一次故障。
4.1 同步 vs 异步 Checkpoint
同步 CKPT:所有 GPU 暂停训练、各自存储分片。一致性好但写 1.3TB CKPT 需 5~10 分钟阻塞。
异步 CKPT:CPU 侧异步拷贝 GPU 显存到主机内存后写磁盘,GPU 继续计算。挑战是确保快照一致性。
4.2 Straggler 检测
记录每次 allreduce 完成时间,某 rank 的 P99 延迟持续高于中位数 2 倍 → 标记为潜在 straggler。常见原因:GPU 降频、RDMA 拥塞、ECC 纠错过多。
4.3 自动节点驱逐
TorchElastic 等框架支持:检测 rank 超时 → 保存 CKPT → 移出错节点、替换备机 → 从 CKPT 恢复并重置 consumed samples → 弹性重启。
---
五、代码实践:DeepSpeed ZeRO-3 训练 7B 模型
8×A100(80GB)训练 7B 模型的配置:
{
"train_batch_size": 32,
"gradient_accumulation_steps": 2,
"bf16": { "enabled": true },
"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": 5e8,
"stage3_prefetch_bucket_size": 5e8,
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9,
"stage3_gather_16bit_weights_on_model_save": true
},
"optimizer": {
"type": "AdamW",
"params": { "lr": 3e-4, "betas": [0.9, 0.95], "eps": 1e-8, "weight_decay": 0.1 }
},
"scheduler": {
"type": "WarmupDecayLR",
"params": { "warmup_min_lr": 0, "warmup_max_lr": 3e-4, "warmup_num_steps": 2000, "total_num_steps": 500000 }
}
}{
"train_batch_size": 32,
"gradient_accumulation_steps": 2,
"bf16": { "enabled": true },
"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": 5e8,
"stage3_prefetch_bucket_size": 5e8,
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9,
"stage3_gather_16bit_weights_on_model_save": true
},
"optimizer": {
"type": "AdamW",
"params": { "lr": 3e-4, "betas": [0.9, 0.95], "eps": 1e-8, "weight_decay": 0.1 }
},
"scheduler": {
"type": "WarmupDecayLR",
"params": { "warmup_min_lr": 0, "warmup_max_lr": 3e-4, "warmup_num_steps": 2000, "total_num_steps": 500000 }
}
}
import deepspeed
model_engine, optimizer, _, _ = deepspeed.initialize(
model=model, config_params=ds_config, model_parameters=model.parameters()
)
_, client_state = model_engine.load_checkpoint(
load_dir="/ckpt/global_step1000",
load_optimizer_states=True,
load_lr_scheduler_states=True
)
dataloader = restore_dataloader(client_state) # 弹性训练关键关键参数
overlap_commreduce_bucket_sizeoffload_*stage3_max_live_parametersgather_16bit_weights_on_model_saveCheckpoint 恢复
import deepspeed
model_engine, optimizer, _, _ = deepspeed.initialize(
model=model, config_params=ds_config, model_parameters=model.parameters()
)
_, client_state = model_engine.load_checkpoint(
load_dir="/ckpt/global_step1000",
load_optimizer_states=True,
load_lr_scheduler_states=True
)
dataloader = restore_dataloader(client_state) # 弹性训练关键
---
六、混合精度:FP8 vs BF16
BF16
FP8(H100/H200)
🛠️ 实战经验:FP8 在小 batch 下收益有限,推荐 global batch ≥ 4M tokens 时切换,避免"通信等计算"。
---
常见误区
误区一:"并行度越高,训练越快"
通信开销随 GPU 数非线性增长。TP=8 时每层增加 allreduce,80 层模型共 160 次,通信量惊人。正确做法:先扩 DP,再开 PP,最后才加 TP。
误区二:"OOM 了就加 GPU"
加 GPU 增加通信成本。先检查 activation_checkpointing:13B 模型在 80GB A100 上可从 75GB 降至 40GB,效果远优于加卡。
误区三:"NCCL 自动选最优算法"
NCCL 拓扑检测依赖 NVLink/PCIe 拓扑正确上报。虚拟化或多 NIC 场景下可能误判,建议用 NCCL_DEBUG=INFO 确认实际拓扑。
---
练习
<details>
<summary><b>参考答案</b></summary>
1.
2.
</details>
---
🚀 下一篇预告:第 8 篇:对齐方法全景——RLHF / DPO / GRPO 深入对比,系统讲解三种对齐方法的核心算法、数学推导与工程实现差异。