前言
随着大模型参数量从 7B、13B 攀升至几十 B、上百 B,传统 PyTorch DDP 数据并行存在致命缺陷:每张 GPU 都会完整复制一份模型、梯度、优化器参数,显存冗余极高,小显存显卡极易 OOM 显存溢出。微软开源的 DeepSpeed 凭借ZeRO 内存分片优化,将训练状态分散到多卡 GPU 甚至 CPU 内存,大幅降低单卡显存占用,让个人多卡服务器也能训练超大模型。
本文结合线下多卡训练实测经验,从底层原理、安装部署、ZeRO Stage1/2/3 完整配置、性能实测对比、高频报错排查全方位梳理 DeepSpeed 落地要点,理清「显存占用」与「训练速度」的核心取舍逻辑,帮开发者快速选对适合自己硬件的训练方案。
LLaMA-Factory 支持通过 DDP 、DeepSpeed 和 FSDP 三种引擎实现单机多卡及多机多卡训练,能有效突破显存瓶颈并大幅提升训练效率 。LLaMA-Factory 提供可视化 WebUI(LLaMA Board),无需编写复杂命令,图形化即可开启、配置 DeepSpeed 分布式训练,解决单卡显存不足、多卡并行加速需求。 适用场景:7B/13B/20B 大模型 LoRA 微调、单机多卡训练、显存紧张场景使用 ZeRO 分片优化。,LLaMA-Factory中做如下配置就可完成多卡训练

一、DeepSpeed 核心底层思想:CPU 内存补充 GPU 显存
DeepSpeed 核心逻辑一句话概括:GPU 显存不够,CPU 内存来兜底。 传统并行方案每张卡留存全套训练参数,而 ZeRO 会把优化器、梯度、模型权重分片分散存储,训练计算时按需在 GPU、CPU 之间传输交换。显存占用越低,CPU/GPU 数据交互越频繁,训练速度损耗越大,这是使用 DeepSpeed 永远绕不开的权衡关系。
官方原生支持两大核心能力:
- ZeRO-offload 卸载:将优化器、模型参数临时缓存至主机内存,释放 GPU 空间,支持更大批次、更大模型加载;
- 内存碎片自动管理:减少张量碎片化浪费,同等显存下支持更长上下文、更大 batch_size。
适用场景:单 / 多卡显存不足以承载完整模型,需要低成本训练大模型;仅单卡且显存充足、模型参数量较小时,不推荐使用,会徒增训练耗时。
二、DeepSpeed 两种安装方式
方式 1:极简 pip 一键安装(新手推荐)
pip install deepspeed
方式 2:源码编译安装(适配本机 CUDA 架构,性能更好)
针对 RTX 30/40 系列(算力 8.6)编译命令:
git clone https://github.com/microsoft/DeepSpeed.git
cd DeepSpeed
rm -rf build
TORCH_CUDA_ARCH_LIST="8.6" DS_BUILD_CPU_ADAM=1 DS_BUILD_UTILS=1 pip install . \
--global-option="build_ext" --global-option="-j8" --no-cache -v \
--disable-pip-version-check 2>&1 | tee build.log
配套 HuggingFace 集成安装
Transformers 原生兼容 DeepSpeed,可直接安装集成包,训练时无需额外适配代码:
pip install transformers[deepspeed]
三、ZeRO 分片技术核心原理:分片替代复制
传统 DDP:所有 GPU 复制全套优化器状态+梯度+模型参数,显存成倍冗余。 ZeRO(Zero Redundancy Optimizer):分片存储而非完整复制,把三类训练状态拆分至多设备,消除显存冗余,分三个渐进优化阶段:
表格
| ZeRO 阶段 | 分片对象 | 显存降低幅度 | 速度损耗 | 适用硬件 |
|---|---|---|---|---|
| Stage1 | 仅优化器状态分片 | 小幅降低 | 几乎无损耗 | 8×24G 充足多卡、追求速度优先 |
| Stage2 | 优化器 + 梯度同时分片 | 中等降低 | 轻微损耗 | 4×24G 均衡多卡,工程最常用 |
| Stage3 | 优化器 + 梯度 + 模型权重全分片 | 大幅降低 | 损耗极大 | 单 / 双卡小显存、13B/20B 超大模型 |
关键补充:ZeRO-Infinity(Stage3 进阶)
在 Stage3 基础上支持把参数卸载到 NVMe 固态硬盘,进一步压榨内存空间,适合上百 B 超大规模模型,普通 7B/13B 微调无需启用。
四、ZeRO 各阶段完整可复用配置文件
所有配置中重复训练参数(学习率调度、混合精度)统一设为auto,会自动读取 Hugging Face Trainer、LLaMA Factory 训练参数,避免参数冲突。
4.1 ZeRO Stage2 通用配置(生产首选均衡方案)
兼顾显存释放与训练速度,绝大多数单机多卡微调优先选用:
json
{
"bfloat16": {
"enabled": "auto"
},
"fp16": {
"enabled": "auto",
"loss_scale": 0,
"loss_scale_window": 1000,
"initial_scale_power": 16,
"hysteresis": 2,
"min_loss_scale": 1
},
"optimizer": {
"type": "AdamW",
"params": {
"lr": "auto",
"betas": "auto",
"eps": "auto",
"weight_decay": "auto"
}
},
"scheduler": {
"type": "WarmupLR",
"params": {
"warmup_min_lr": "auto",
"warmup_max_lr": "auto",
"warmup_num_steps": "auto"
}
},
"zero_optimization": {
"stage": 2,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"allgather_partitions": true,
"allgather_bucket_size": 2e8,
"overlap_comm": true,
"reduce_scatter": true,
"reduce_bucket_size": 2e8,
"contiguous_gradients": true
},
"gradient_accumulation_steps": "auto",
"gradient_clipping": "auto",
"train_batch_size": "auto",
"train_micro_batch_size_per_gpu": "auto",
"steps_per_print": 100000
}
核心参数说明:
offload_optimizer.device: cpu:优化器存放至内存,释放显存;pin_memory开启页锁定内存,加速 CPU/GPU 数据传输;overlap_comm:通信与计算并行,数值越大通信越快、显存占用越高,按需平衡;reduce_bucket_size:梯度聚合分片大小,自动适配模型尺寸无需手动修改。
4.2 ZeRO Stage3 超大显存节约配置
模型过大、单卡无法加载完整权重时使用,速度会明显下降:
{
"bfloat16": {
"enabled": "auto"
},
"fp16": {
"enabled": "auto",
"loss_scale": 0,
"loss_scale_window": 1000,
"initial_scale_power": 16,
"hysteresis": 2,
"min_loss_scale": 1
},
"optimizer": {
"type": "AdamW",
"params": {
"lr": "auto",
"betas": "auto",
"eps": "auto",
"weight_decay": "auto"
}
},
"scheduler": {
"type": "WarmupLR",
"params": {
"warmup_min_lr": "auto",
"warmup_max_lr": "auto",
"warmup_num_steps": "auto"
}
},
"zero_optimization": {
"stage": 3,
"offload_optimizer": {
"device": "cpu",
"pin_memory": true
},
"offload_param": {
"device": "cpu",
"pin_memory": true
},
"overlap_comm": true,
"contiguous_gradients": true,
"sub_group_size": 1e9,
"reduce_bucket_size": "auto",
"stage3_prefetch_bucket_size": "auto",
"stage3_param_persistence_threshold": "auto",
"stage3_max_live_parameters": 1e9,
"stage3_max_reuse_distance": 1e9,
"stage3_gather_fp16_weights_on_model_save": true
},
"gradient_accumulation_steps": "auto",
"gradient_clipping": "auto",
"train_batch_size": "auto",
"train_micro_batch_size_per_gpu": "auto",
"steps_per_print": 100000,
"wall_clock_breakdown": false
}
新增offload_param:将模型权重也卸载至内存,显存占用达到最低,代价是大量数据交换,训练速度大幅降低。
4.3 启动训练命令模板
# 指定GPU数量、端口、ds配置文件
deepspeed --master_port 29500 --num_gpus=4 train.py \
--deepspeed ds_zero2_config.json
--master_port:分布式通信端口,多任务并行需修改避免占用;--num_gpus:使用显卡数量,不填默认调用全部 GPU。
五、显存占用预估工具(训练前提前避坑)
DeepSpeed 提供内置预估函数,提前计算 ZeRO-3 模式下 CPU、内存占用,避免内存不足进程被杀:
from transformers import AutoModel
from deepspeed.runtime.zero.stage3 import estimate_zero3_model_states_mem_needs_all_live
# 替换你的基座模型
model = AutoModel.from_pretrained("Qwen2.5-7B-Instruct")
# 单节点4卡预估
estimate_zero3_model_states_mem_needs_all_live(model, num_gpus_per_node=4, num_nodes=1)
使用原则:能不用 ZeRO 就不用;显存充足优先 Stage2,万不得已再选用 Stage3。
六、线下实测:Stage2 / Stage3 性能对比
测试环境:单卡 RTX4090 24G,7B 模型 LoRA 微调,batch_size=2
- ZeRO Stage2 实测数据
- 原始显存占用:20513MiB → 开启后 17349MiB,释放约 3GB 显存;
- 训练速度:1.3 iter/s → 0.77 iter/s,速度下降约 40%;
- 痛点:释放显存有限,不足以提升 batch_size,总训练时长变长。
- ZeRO Stage3 实测数据 显存占用可降低 50% 以上,但速度损耗极其严重:原本 6 小时训练任务,开启后耗时超 48 小时,日常微调不推荐使用。
七、DeepSpeed 常见踩坑与完整解决方案
1. 进程无报错直接被系统杀死
原因:offload 后大量参数存入系统内存,物理内存不足,系统 OOM Killer 终止进程。 解决:
- 先用预估脚本计算内存需求,
free -h查看空闲内存; - 减少 offload 范围,优先只卸载优化器,关闭
offload_param; - 增加机器物理内存或更换多机分布式训练。
2. 训练 loss 持续变为 NaN
原因:混合精度缩放值不合适、学习率过高、梯度爆炸。 解决:
- 配置开启
gradient_clipping: 1.0梯度裁剪; - 降低学习率,微调推荐 5e-05 及以下;
- FP16 模式调大
initial_scale_power,优先使用 BF16 训练。
3. ZeRO offload 模式无法自定义分层学习率
DeepSpeed 内置 AdamW 优化器会接管参数更新逻辑,自定义优化器必须同时实现 CPU、GPU 两套版本,开发成本极高。 解决:LoRA 微调无需分层学习可直接使用内置优化器;需要自定义时放弃 offload,改用纯 GPU ZeRO Stage1。
4. VS Code 无法断点调试 DeepSpeed 进程
DeepSpeed 分布式进程通信机制不兼容 VS Code 调试插件,官方无适配方案。 解决:调试阶段关闭 DeepSpeed,单卡原生 Trainer 验证逻辑,正式训练再启用 ZeRO。
5. 训练控制台无输出、GPU 满载看不到进度
多卡分片通信会屏蔽部分日志输出,仅 GPU 利用率无法判断训练状态。 解决:调小steps_per_print,每几十步打印一次 loss,监控训练进度。
八、DeepSpeed 推理补充说明
超大模型推理同样可复用 ZeRO Stage3 配置,推理阶段会自动忽略 optimizer、学习率等训练参数,仅使用分片加载逻辑,适合单卡低显存机器运行大模型推理。进阶 ZeRO-Infinity 支持 SSD 分担内存,适合超大规模离线推理场景。
九、落地选型总结(实操建议)
- 硬件充足(4/8×24G)、追求训练速度:选用 ZeRO Stage2,仅卸载优化器,速度损耗可控;
- 显存紧张、单 / 双卡跑 13B/20B 模型:临时使用 ZeRO Stage3,项目长期不推荐;
- LoRA 轻量化微调:优先 Stage2,大部分场景足够释放显存;
- 硬件富余、单卡完全装下模型:直接原生 DDP,不启用 DeepSpeed,避免速度损耗;
- 内存资源有限时,严禁同时开启
offload_optimizer与offload_param,极易触发系统杀进程。
一、前置准备
1. 安装 DeepSpeed 依赖
pip install deepspeed
2. 准备 DeepSpeed 配置文件 ds_config.json
项目 examples/deepspeed/ 目录内置官方模板:
ds_z0_config.jsonZeRO-0(不做分片,仅多卡数据并行)ds_z2_config.jsonZeRO-2(优化器 + 梯度分片,均衡速度 / 显存,4 卡 24G 首选)ds_z3_config.jsonZeRO-3(权重全分片,显存占用最低,适合单 / 双卡跑超大模型)LLaMA Fact...
通用 ZeRO-2 配置(生产推荐)
{
"bfloat16": {"enabled": "auto"},
"fp16": {"enabled": "auto"},
"optimizer": {
"type": "AdamW",
"params": {
"lr": "auto",
"betas": "auto",
"eps": "auto",
"weight_decay": "auto"
}
},
"scheduler": {"type": "WarmupLR", "params": {"warmup_min_lr": "auto", "warmup_max_lr": "auto", "warmup_num_steps": "auto"}},
"zero_optimization": {
"stage": 2,
"offload_optimizer": {"device": "cpu", "pin_memory": true},
"allgather_partitions": true,
"allgather_bucket_size": 2e8,
"overlap_comm": true,
"reduce_scatter": true,
"reduce_bucket_size": 2e8,
"contiguous_gradients": true
},
"gradient_accumulation_steps": "auto",
"gradient_clipping": "auto",
"train_batch_size": "auto",
"train_micro_batch_size_per_gpu": "auto",
"steps_per_print": 100
}
二、启动 LLaMA-Factory WebUI
1. 指定可用显卡(多卡必须配置)
# 限定使用0、1、2、3四张显卡
export CUDA_VISIBLE_DEVICES=0,1,2,3
# 启动可视化微调面板
llamafactory-cli webui
访问地址:http://localhost:7860
三、WebUI 界面开启 DeepSpeed 分步操作
步骤 1:进入「训练」标签页,基础参数配置
- 模型设置
model_name_or_path:本地基座模型完整路径finetuning_type:LoRA(轻量化微调)template:匹配基座模型对话模板(qwen/llama3 等)
- 数据集设置
dataset_dir:数据集根目录dataset:dataset_info.json注册的数据集名称
- 训练超参
per_device_train_batch_size、learning_rate、num_train_epochs按需填写
步骤 2:找到高级设置「DeepSpeed」选项(核心)
页面下方高级加速 / 分布式 区域存在 deepspeed 下拉输入框,两种配置方式:
方式 A:选择内置 ds 模板(最简单,新手推荐)
下拉菜单内置预设配置:ds_z0、ds_z2、ds_z3、ds_z2_offload 等,直接选中即可自动加载对应 json 配置文件,无需手动填写路径CSDN博...。
方式 B:手动填写自定义配置文件绝对路径
若修改过自定义 ds_config.json,直接填入文件完整路径,示例:
/home/xxx/LLaMA-Factory/examples/deepspeed/ds_z2_config.json
步骤 3:确认精度与混合精度
WebUI 中 bf16 勾选开启,与 DeepSpeed 配置内 bfloat16.enabled="auto" 保持兼容,避免 loss 出现 NaN。
步骤 4:点击「开始训练」自动启用多卡 DeepSpeed
WebUI 底层自动封装 FORCE_TORCHRUN=1 分布式启动指令,无需手动写 bash 脚本,自动根据显卡数量执行多卡训练LLaMA Fact...。
四、ZeRO 阶段选型界面配置建议
表格
| 硬件环境 | WebUI 选择 DeepSpeed 模板 | 适用场景 |
|---|---|---|
| 8×24G 充足多卡 | ds_z0 / ds_z2 | 追求训练速度优先 |
| 4×24G 均衡多卡 | ds_z2(推荐) | 显存释放与速度平衡,日常 LoRA 微调首选 |
| 单 / 双卡 24G,跑 13B/20B 大模型 | ds_z3 | 最大限度节省显存,代价是训练速度变慢 |
五、常见界面报错与解决
1. 报错:找不到 deepspeed 配置文件
- 原因:填写的文件路径错误、文件名拼写错误;使用内置模板但文件缺失
- 解决:复制配置文件绝对路径;使用官方内置模板,不要自定义文件名
2. 多卡训练显存负载不均衡
- 原因:ZeRO stage 选择错误,通信桶参数不匹配
- 解决:4 卡优先选择 ds_z2;不推荐直接使用 ds_z3 日常微调
3. 训练 loss 出现 NaN
- 原因:混合精度冲突、学习率过高
- 解决:WebUI 勾选 bf16,降低学习率至 5e-5 以内,开启梯度裁剪
4. 进程被系统 OOM 杀死
- 原因:ZeRO-3 开启 cpu 卸载,占用大量系统内存
- 解决:改用 ZeRO-2;关闭
offload_param仅保留优化器卸载
六、命令行 YAML 配套参考(WebUI 导出配置)
WebUI 训练完成后可导出 yaml 训练配置,DeepSpeed 核心片段:
stage: sft
do_train: true
model_name_or_path: /root/model/Qwen2.5-7B-Instruct
finetuning_type: lora
template: qwen
dataset: my_train_data
cutoff_len: 1024
per_device_train_batch_size: 4
learning_rate: 5e-5
num_train_epochs: 10
# DeepSpeed 核心配置
trainer:
type: deepspeed
deepspeed: examples/deepspeed/ds_z2_config.json
如需离线命令行训练,直接执行:
FORCE_TORCHRUN=1 llamafactory-cli train train_config.yaml
七、落地最佳实践
- 优先使用 WebUI 内置 ds_z2 模板,适配绝大多数多卡微调场景;
- 超大模型(13B/20B)、单卡显存不足时,再选用 ds_z3;
- 启动 WebUI 前务必通过
CUDA_VISIBLE_DEVICES限定显卡,防止占用全部 GPU; - 训练前小规模样本测试流程,确认 DeepSpeed 正常启动、无显存溢出,再全量训练。