DeepSpeed是由Microsoft开发的大规模分布式训练优化框架,旨在支持更大规模的模型训练,提供更多显存优化策略。
主要优势和功能:
主流训练方案:GPU + PyTorch + Megatron-LM + DeepSpeed 是目前业界训练超大模型的标准组合。
ZeRO(Zero Redundancy Optimizer)去除数据并行中的冗余存储,每张卡只存储一部分模型状态,从而大幅减少显存占用。在执行逻辑上它仍是数据并行,但能达到模型并行的显存优化效果。
模型训练时,显存主要被两部分占用:
以1.5B参数GPT-2为例,fp16混合精度下,虽然参数只需要3GB,但模型状态总共需要24GB,优化器状态是显存最大消耗者。
ZeRO分三个阶段,逐步对不同部分进行分片存储:
| ZeRO阶段 | 优化器状态 | 梯度 | 参数 | 显存减少 | 通信量增加 |
|---|---|---|---|---|---|
| stage 0 | 完整存储 | 完整存储 | 完整存储 | 1x | 基准 |
| stage 1 | 分片存储 | 完整存储 | 完整存储 | 4x | 不变 |
| stage 2 | 分片存储 | 分片存储 | 完整存储 | 8x | 不变 |
| stage 3 | 分片存储 | 分片存储 | 分片存储 | N倍 (N=GPU数) | +50% |
举例:64块GPU,ZeRO-3可以把显存减少到1/64,让千亿模型训练成为可能。
ZeRO-Offload将模型状态卸载(offload)到CPU内存,利用CPU内存来扩展可训练模型大小,让GPU单卡也能训练更大的模型。
计算流程:
关键优化:计算与通信重叠。GPU在反向传播阶段,一边计算梯度,一边把已经算好的梯度bucket传输给CPU,当反向结束,CPU已经拿到大部分梯度了。
ZeRO-Infinity进一步扩展了offload思想,可以将参数offload到NVMe固态硬盘,理论上可以用有限GPU显存训练任意大的模型:
从左到右,速度越来越慢,显存需求越来越小:
速度:Stage 0 (DDP) > Stage 1 > Stage 2 > Stage 2 + offload > Stage 3 > Stage 3 + offload
显存:Stage 0 (DDP) < Stage 1 < Stage 2 < Stage 2 + offload < Stage 3 < Stage 3 + offload1pip install deepspeed==0.8.1
2sudo apt-get install openmpi-bin libopenmpi-dev
3pip install mpi4py1import deepspeed
2
3# 定义模型、优化器
4model = Model()
5criterion = nn.CrossEntropyLoss()
6optimizer = build_optimizer(model, args)
7
8# DeepSpeed配置
9deepspeed_config = {
10 "train_micro_batch_size_per_gpu": 32,
11 "gradient_accumulation_steps": 1,
12 "optimizer": {
13 "type": "AdamW",
14 "params": {"lr": 3e-5}
15 },
16 "fp16": {"enabled": True},
17 "zero_optimization": {
18 "stage": 3,
19 "offload_optimizer": {
20 "device": "cpu",
21 "pin_memory": true
22 },
23 "offload_param": {
24 "device": "cpu",
25 "pin_memory": true
26 }
27 }
28}
29
30# 初始化DeepSpeed引擎
31model_engine, optimizer, _, _ = deepspeed.initialize(
32 config=deepspeed_config,
33 model=model,
34 model_parameters=model.parameters()
35)1for batch in dataloader:
2 # 前向
3 outputs = model_engine(inputs)
4 loss = criterion(outputs, labels)
5
6 # 反向
7 model_engine.backward(loss)
8
9 # 步进
10 model_engine.step()1# 保存
2model_engine.save_checkpoint(save_path, save_latest=True)
3
4# 加载
5model_engine.load_checkpoint(load_path, load_module_only=True)
6
7# 转换为完整pytorch模型
8# 使用zero_to_fp32.py脚本
9python zero_to_fp32.py . pytorch_model.bin1deepspeed --hostfile=hostfile train.py --deepspeed_config config.jsonZeRO-2 配置示例:
1{
2 "zero_optimization": {
3 "stage": 2,
4 "offload_optimizer": {
5 "device": "cpu",
6 "pin_memory": true
7 },
8 "allgather_partitions": true,
9 "allgather_bucket_size": 2e8,
10 "overlap_comm": true,
11 "reduce_scatter": true,
12 "reduce_bucket_size": 2e8,
13 "contiguous_gradients": true
14 }
15}ZeRO-3 配置示例:
1{
2 "zero_optimization": {
3 "stage": 3,
4 "offload_optimizer": {
5 "device": "cpu",
6 "pin_memory": true
7 },
8 "offload_param": {
9 "device": "cpu",
10 "pin_memory": true
11 },
12 "overlap_comm": true,
13 "contiguous_gradients": true,
14 "sub_group_size": 1e9,
15 "reduce_bucket_size": "auto",
16 "stage3_prefetch_bucket_size": "auto",
17 "stage3_param_persistence_threshold": "auto",
18 "stage3_max_live_parameters": 1e9,
19 "stage3_max_reuse_distance": 1e9,
20 "stage3_gather_16bit_weights_on_model_save": true
21 }
22}关键参数说明:
overlap_comm: 是否让通信和计算重叠,开启可加速allgather_bucket_size / reduce_bucket_size: 控制分桶大小,越大通信越快但占更多显存。OOM时需要调小stage3_max_live_parameters: 控制GPU上同时保留的完整参数数量上限,OOM时调小batch_size=1 + 梯度累积gradient_checkpointingallgather_bucket_size和reduce_bucket_sizeDeepSpeed提供显存估算工具:
1from transformers import AutoModel
2from deepspeed.runtime.zero.stage3 import estimate_zero3_model_states_mem_needs_all_live
3
4model = AutoModel.from_pretrained("bigscience/T0_3B")
5estimate_zero3_model_states_mem_needs_all_live(model, num_gpus_per_node=2, num_nodes=1)输出示例:
per CPU | per GPU | Options
70.00GB | 0.25GB | offload_param=cpu , offload_optimizer=cpu
62.23GB | 2.84GB | offload_param=none, offload_optimizer=cpu
0.74GB | 23.58GB | offload_param=none, offload_optimizer=none可以根据这个输出选择合适的配置。
ModuleNotFoundError: No module named 'torch._six'
1# from torch._six import string_classes
2int_classes = int
3string_classes = strloss是NaN
启动时进程被杀死,无traceback
单卡也能用DeepSpeed吗?
ZeRO-3比ZeRO-2慢很多,怎么优化?
stage3_param_persistence_thresholdmodel1 slots=8
model2 slots=8A: 传统数据并行中,每个GPU都保存完整的参数、梯度、优化器状态,有大量冗余存储,显存利用率低。ZeRO通过分片存储,每个GPU只保存一部分,去除冗余,在数据并行的并行度下,达到了模型并行的显存缩减效果。
A:
A: ZeRO-Offload把优化器状态和参数放到CPU内存,只在需要时传到GPU计算,完成后再传回去。用CPU内存换GPU显存,让小GPU也能训练大模型。关键优化是计算和通信重叠,隐藏传输延迟。
A:
A: 根据GPU显存从多到少依次尝试:
A: ZeRO是显存优化的数据并行,3D并行是数据+张量+流水线的组合并行。根据论文,当GPU数量增加到千量级,3D并行的效率比纯ZeRO3更高。ZeRO在大规模集群上通信效率不如3D并行。实际中常常结合使用:Megatron-LM做张量+流水线并行,DeepSpeed做ZeRO数据并行。