DeepSpeed 是由微软开源的高性能深度学习训练优化引擎,专注于帮助研究人员和工程团队在分布式环境中高效地训练超大规模模型。其核心目标是提供 高吞吐、低内存占用、低成本 的分布式训练方案,让数千亿甚至万亿级参数模型的训练成为可能。本文将从 DeepSpeed 的核心原理、关键组件、代码示例 及 实现过程详解 等方面做详细阐述,帮助读者更好地理解并使用 DeepSpeed。
在深度学习模型参数规模不断增长的趋势下,传统的数据并行(Data Parallel)已经无法满足超大模型的内存需求和训练效率。DeepSpeed 的出现,旨在通过多项技术创新大幅优化大模型训练的资源利用效率与训练速度:
总体而言,DeepSpeed 让 “大模型” 能在 “相对少的硬件资源” 上实现高效训练与推理,极大地降低了研究和产业落地的门槛。
在训练超大模型时,最主要的内存开销来自 优化器状态 (Optimizer States)、梯度 (Gradients) 和 模型权重 (Parameters)。传统的数据并行会在每张 GPU 上保留完整的这三份拷贝,因此当模型参数量超过数十亿甚至上千亿时,单卡内存远远不足。
ZeRO 的全称是 Zero Redundancy Optimizer,它通过 分块(Sharding) 的方式将参数、梯度和优化器状态分别切分,分配到不同的 GPU 上,从而 消除冗余:
在 ZeRO-3 模式下,每张 GPU 仅持有完整模型参数的一部分,以及相应的部分梯度和优化器状态。其余切分数据存放在其他 GPU 上,通过全局通信进行同步计算。
在 ZeRO-3 模式下,相比传统数据并行,单卡内存占用可以减少 数倍到数十倍。在多机多卡环境中,ZeRO 能接近线性地扩展到上千张 GPU。
深度学习的大规模训练常结合多种并行方式,DeepSpeed 也为以下模式提供了支持:
数据并行 (Data Parallel, DP)
模型并行 (Model Parallel, MP)
流水线并行 (Pipeline Parallel, PP)
DeepSpeed 提供便捷的接口让用户在同一引擎中同时使用 ZeRO + MP + PP 等组合并行策略。
DeepSpeed Engine 是一个高层封装,统管 通信策略、优化器切分、梯度汇总 等功能,对外提供易用的 Python 接口。核心包括:
DeepSpeed.initialize(...)
deepspeed_config.json
配置文件,初始化 ZeRO、并行策略等;model_engine
与 optimizer
、training_dataloader
。model_engine.forward/backward/step
model
的前向、后向、更新三步;自动微调
在推理阶段,DeepSpeed Inference Engine 提供大模型多卡并行推理能力:
以下通过两个示例演示 DeepSpeed 的基本用法:
.
├── train.py
└── deepspeed_config.json
deepspeed_config.json
(ZeRO 配置示例){
"train_batch_size": 8,
"gradient_accumulation_steps": 2,
"fp16": {
"enabled": true
},
"zero_optimization": {
"stage": 2
}
}
train_batch_size
: 全局训练的 batch size(多卡合计),与 gradient_accumulation_steps
结合来控制单次迭代的有效批次。fp16.enabled
: 开启混合精度训练。zero_optimization.stage
: 设置 ZeRO 的级别(1~3)。train.py
import torch
import torch.nn as nn
import torch.optim as optim
import deepspeed
from torch.utils.data import Dataset, DataLoader
# 1. 简易数据集定义
class RandomDataset(Dataset):
def __init__(self, size=64, length=1000):
super().__init__()
self.size = size
self.length = length
self.data = torch.randn(length, size)
self.labels = torch.randint(0, 2, (length,))
def __len__(self):
return self.length
def __getitem__(self, idx):
return self.data[idx], self.labels[idx]
# 2. 简单模型定义
class SimpleModel(nn.Module):
def __init__(self, input_dim=64, hidden_dim=32):
super(SimpleModel, self).__init__()
self.linear1 = nn.Linear(input_dim, hidden_dim)
self.relu = nn.ReLU()
self.linear2 = nn.Linear(hidden_dim, 2)
def forward(self, x):
x = self.relu(self.linear1(x))
return self.linear2(x)
def main():
# DeepSpeed 将通过命令行/脚本参数解析 config 等
import argparse
parser = argparse.ArgumentParser()
parser = deepspeed.add_config_arguments(parser)
args = parser.parse_args()
# 1. 初始化数据
dataset = RandomDataset()
train_loader = DataLoader(dataset, batch_size=4)
# 2. 构建模型
model = SimpleModel()
# 3. 定义优化器 (DeepSpeed需要原生参数)
optimizer = optim.Adam(model.parameters(), lr=1e-3)
# 4. 初始化 DeepSpeed Engine
model_engine, optimizer_engine, train_loader, _ = deepspeed.initialize(
model=model,
optimizer=optimizer,
args=args,
training_data=dataset # 也可传入 train_loader
)
# 5. 训练循环
for epoch in range(3):
for step, batch in enumerate(train_loader):
inputs, labels = batch
inputs, labels = inputs.to(model_engine.local_rank), labels.to(model_engine.local_rank)
outputs = model_engine(inputs)
loss_fn = nn.CrossEntropyLoss()
loss = loss_fn(outputs, labels)
# DeepSpeed的后向与优化 step
model_engine.backward(loss)
model_engine.step()
if step % 10 == 0:
print(f"Epoch {epoch}, Step {step}, Loss={loss.item():.4f}")
if __name__ == "__main__":
main()
deepspeed train.py --deepspeed_config deepspeed_config.json
或指定 --num_gpus
进行多卡训练:
deepspeed --num_gpus=4 train.py --deepspeed_config deepspeed_config.json
Hugging Face Transformers 自带 DeepSpeed 支持,可在 Trainer
或 Accelerate
中使用。下面以 Trainer
为例:
from transformers import Trainer, TrainingArguments, AutoModelForSequenceClassification, AutoTokenizer
import datasets
import deepspeed
model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)
# 加载 IMDb 二分类数据集
imdb = datasets.load_dataset("imdb")
def tokenize_fn(examples):
return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=128)
train_data = imdb["train"].map(tokenize_fn, batched=True)
test_data = imdb["test"].map(tokenize_fn, batched=True)
train_data.set_format("torch", columns=["input_ids", "attention_mask", "label"])
test_data.set_format("torch", columns=["input_ids", "attention_mask", "label"])
training_args = TrainingArguments(
output_dir="./ds_transformers",
per_device_train_batch_size=4,
per_device_eval_batch_size=4,
num_train_epochs=1,
logging_steps=100,
evaluation_strategy="epoch",
save_strategy="epoch",
# 指定 DeepSpeed 配置
deepspeed="./ds_config.json"
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_data,
eval_dataset=test_data,
)
trainer.train()
其中 ds_config.json
与上例类似,指定 ZeRO stage 及 FP16 等信息。运行时仅需 python your_script.py
,Transformers 会自动调用 DeepSpeed 进行分布式训练。
"zero_optimization": {
"stage": 3,
"contiguous_gradients": true,
"overlap_comm": true,
"reduce_scatter": true,
"reduce_bucket_size": 200000000
}
adamw
)和学习率策略。DeepSpeed.initialize(...) 做了以下几件事:
model_engine
和 optimizer_engine
。training_data
或现有的 train_loader
传入,用于自动分发到多 GPU。训练循环中,代替原生的 loss.backward()
和 optimizer.step()
,使用 model_engine.backward(loss)
与 model_engine.step()
,让 DeepSpeed 内部处理梯度通信、同步。
以 ZeRO-2 为例:
exp_avg
、exp_avg_sq
)分割到不同 GPU。ZeRO-3 进一步把模型参数本身也做切分,内存占用更低,但通信量更大。
挑选合适的 ZeRO Stage
结合 Pipeline 并行 / 张量并行
注意通信开销和网络带宽
推理阶段也可用 DeepSpeed
与 Hugging Face Transformers 等生态集成
DeepSpeed 通过 ZeRO Optimizer、多重并行策略 与 高性能引擎 的深度整合,帮助研究者和企业以相对有限的 GPU 资源训练超大规模模型。本文详细介绍了 DeepSpeed 的原理、关键组件及示例代码,希望能为读者搭建或优化大模型训练流程提供帮助。
如果你在项目中需要训练数十亿甚至上千亿参数的大模型,不妨试试 DeepSpeed —— 它或许能让大模型训练的门槛大幅降低,并在保证吞吐的同时显著节省显存和算力投入。祝大家在大模型的世界里训练顺利、研发愉快!
【哈佛博后带小白玩转机器学习】 哔哩哔哩_bilibili
总课时超400+,时长75+小时