源码导读:从 deepspeed.initialize() 开始
13.1 顶层目录地图
DeepSpeed/
├── deepspeed/ ← Python 主代码(本章重点)
│ ├── __init__.py 入口,导出 initialize / init_inference / tp_model_init
│ ├── runtime/ 训练 runtime
│ │ ├── engine.py DeepSpeedEngine(forward / backward / step / save)
│ │ ├── config.py 顶层 ds_config 解析
│ │ ├── bf16_optimizer.py BF16 wrapper(loss scaling、master fp32)
│ │ ├── fp16/ FP16 dynamic loss scaler
│ │ ├── zero/ ZeRO 全套(stage_1_and_2.py、stage3.py、partitioned_param_coordinator.py、parameter_offload.py、offload_config.py、muon/)
│ │ ├── pipe/ Pipeline 训练引擎(engine.py、schedule.py、topology.py、p2p.py)
│ │ ├── tensor_parallel/ DS 原生 TP(与 Megatron 互操作)
│ │ ├── sequence_parallel/ 序列并行(Ulysses)
│ │ ├── comm/ 通信原语包装
│ │ ├── superoffload/ 2026-03 SuperOffload
│ │ ├── zenflow/ 2025-10 选择性梯度更新
│ │ ├── domino/ 2024-11 异步 TP
│ │ ├── data_pipeline/ data efficiency / curriculum
│ │ ├── hybrid_engine.py DS-Chat / RLHF 用
│ │ └── activation_checkpointing/
│ ├── inference/ 推理 runtime(v1 engine.py、v2/)
│ ├── ops/ Python 封装的 fused op(adam / lamb / lion / muon / quantizer)
│ ├── moe/ layer.py / sharded_moe.py / experts.py
│ ├── nvme/ NVMe IO
│ ├── pipe/ PipelineModule / LayerSpec 公开入口
│ ├── launcher/ deepspeed CLI 启动器
│ ├── module_inject/ 推理 kernel 替换(auto_tp.py、replace_policy.py)
│ ├── monitor/ TensorBoard / WandB / CSV / Comet
│ ├── compression/ 量化 / 剪枝 / 蒸馏
│ ├── elasticity/ 弹性扩缩容
│ ├── compile/ 2025-04 DeepCompile(torch.compile 集成)
│ ├── sequence/ Ulysses + ALST(fpdt_layer.py、auto_sp.py)
│ ├── checkpoint/ shard 合并 / universal checkpoint
│ ├── linear/ TP 化的 Linear
│ ├── autotuning/ config 自动搜索
│ ├── utils/ 工具(含 zero_to_fp32.py 转换脚本)
│ └── ...
├── op_builder/ C++/CUDA op 编译规则(每个 op 一个 .py)
├── csrc/ CUDA / C++ 源码
├── tests/ 单元测试(unit/runtime/zero/ 是读懂 ZeRO 的好入口)
├── docs/ API doc 源码
├── benchmarks/ 性能基准
├── blogs/ 官方博客(很多技术细节藏在这里)
├── docker/ Dockerfile
├── requirements/ 各组依赖
└── setup.py package + ds_report 入口
13.2 三条主线代码
| 主线 | 核心文件 |
|---|---|
| 训练初始化 | deepspeed/__init__.py · initialize() → runtime/engine.py |
| ZeRO 分片 | runtime/zero/stage_1_and_2.py、runtime/zero/stage3.py |
| 推理引擎 | inference/engine.py、inference/v2/ |
13.3 训练调用栈(rank 0 视角)
拉起 N 个进程,注入 ENV"] Launcher --> Py["train.py 调 deepspeed.initialize()"] Py --> Init["__init__.initialize()"] Init --> Cfg["DeepSpeedConfig 解析 ds_config.json
(runtime/config.py)"] Init --> Dist["init_process_group
(runtime/comm/comm.py)"] Init --> Pick{"按 zero stage
选优化器"} Pick -- 0/1/2 --> Z12["DeepSpeedZeroOptimizer
runtime/zero/stage_1_and_2.py"] Pick -- 3 --> Z3["DeepSpeedZeroOptimizer_Stage3
runtime/zero/stage3.py"] Z12 --> Eng["DeepSpeedEngine 构造
runtime/engine.py · DeepSpeedEngine.__init__()"] Z3 --> Eng Eng --> Hook["注册各类 hook(grad / param / pre-step / post-step)"] Eng --> Ret[(返回 engine, optimizer,
loader, scheduler)] Ret --> Loop[训练循环: engine.backward / engine.step]
13.4 runtime/engine.py:DeepSpeedEngine 的 5 块
DeepSpeedEngine 这个类大约 3000+ 行,分块阅读:
| 块 | 关键方法 | 做什么 |
|---|---|---|
| A | __init__() + _configure_*() | 读 config、init 分布式、选 stage、装 hook |
| B | forward() | 包 forward;处理 fp16/bf16 cast |
| C | backward() | 触发梯度切分、reduce-scatter |
| D | step() | 触发 optimizer.step、参数广播、scheduler.step |
| E | save_checkpoint() / load_checkpoint() | 多 rank shard 协同保存 / 恢复 |
13.5 runtime/zero/stage3.py:ZeRO-3 状态机
这是整个 DS 最难读的文件之一(~2500 行)。建议这样读:
- 先读
PartitionedParamCoordinator:参数状态机 NOT_AVAILABLE / INFLIGHT / AVAILABLE; - 再读
DeepSpeedZeRoOffload:参数 offload 到 CPU / NVMe 的实现; - 再读
DeepSpeedZeroOptimizer_Stage3的backward / step:怎么触发 reduce-scatter; - 最后看
parameter_offload.py:hook 怎么挂的,何时 release 别人那 (N-1)/N 的参数。
13.6 launcher/:deepspeed CLI 的实现
| 文件 | 角色 |
|---|---|
runner.py | deepspeed 命令的 main,解析 args,分发到单机 / 多机 runner |
launch.py | 实际启动 N 个 Python 子进程,相当于自家版本的 torchrun |
multinode_runner.py | 多机时通过 SSH / pdsh / mpirun 跨机拉起 |
launcher_helper.py | 解析 hostfile / include / exclude |
13.7 op_builder/ + csrc/:怎么编出 fused kernel
| 目录 | 说明 |
|---|---|
op_builder/builder.py | 基类 OpBuilder,子类用于 JIT 编译 .cu/.cpp |
op_builder/cpu_adam.py | CPUAdam op 编译规则 |
op_builder/fused_adam.py | FusedAdam GPU op |
op_builder/async_io.py | NVMe libaio |
csrc/adam/ | Adam fused kernel 真实 .cu 文件 |
csrc/aio/ | libaio 实现 |
csrc/cpu_adam/ | CPU Adam(AVX-512 优化) |
想加一个自己的 fused op?模板:在 csrc/myop/ 写 .cu 和 binding,op_builder/myop.py 写编译规则,op_builder/__init__.py 注册到 ALL_OPS。
13.8 inference/:两套推理引擎
| 文件 / 目录 | 角色 |
|---|---|
inference/engine.py | v1:init_inference 实现 |
inference/v2/ | v2 / FastGen 全栈 |
module_inject/ | 把 HF 模型里的 LlamaAttention 等替换成 DS fused 版的 patch 实现 |
inference/quantization/ | int8 / fp8 量化推理 |
13.9 checkpoint/:从 ZeRO shard 到 HF 模型
| 脚本 | 用途 |
|---|---|
checkpoint/utils.py | shard 拼合工具 |
checkpoint/zero_to_fp32.py | 最常用:把 ZeRO checkpoint 转 fp32 HF |
checkpoint/universal_checkpoint.py | 跨硬件 / 跨配置的"通用 checkpoint" |
13.10 阅读路线总结
"读完 DeepSpeed"是个庞大目标,建议这样推进:
- 跑通最小例子(本书 ch03):建立感觉;
- 读
__init__.py+runtime/config.py:理解配置驱动; - 顺着
DeepSpeedEngine.__init__看一遍:理解初始化; - 挑
stage_1_and_2.py读 backward / step:先看简单 stage; - 再啃
stage3.py+parameter_offload.py:ZeRO-3 状态机; - 顺手看一下
launcher/runner.py:理解多机; - 有 fused op 兴趣再看
op_builder/+csrc/; - 动手提一个 PR(哪怕修 doc),跑通 contribution 流程。
13.11 想提 PR?从这里入手
| 改动类型 | 对应文件 |
|---|---|
| 新优化器 | ops/<new>/ + runtime/zero/stage_*.py 注册 |
| 新 ZeRO 字段 | runtime/zero/config.py |
| 新 monitor 后端 | monitor/ 加 backend |
| 新硬件 accelerator | accelerator/ |
| 新 launcher 后端(k8s 等) | launcher/multinode_runner.py |
| 修 doc | docs/ + blogs/ |
| fused kernel | csrc/ + op_builder/ |
| 推理 kernel inject 支持新模型 | module_inject/<model>.py |
13.12 延伸阅读
| 资源 | 用途 |
|---|---|
GitHub deepspeedai/DeepSpeed | 主仓库 issues / PRs |
deepspeed.ai | 官方文档站 |
| 论文 ZeRO (1910.02054) | ZeRO 数学基石 |
| 论文 ZeRO-Offload (2101.06840) | CPU offload |
| 论文 ZeRO-Infinity (2104.07857) | NVMe offload |
| 论文 ZeRO++ (2306.10209) | 分层通信 |
blogs/ 目录 | SuperOffload / ZenFlow / Muon / DeepCompile 等最新进展 |
HuggingFace transformers trainer.py | HF 集成端的实现 |
| 本目录 Megatron-LM 那本书 | 对比 ZeRO 与 TP/PP 的差异 |
| 本目录 LLaMA-Factory ch10 | 看上层框架怎么把 DS 当后端用 |
13.13 Stage 3 状态机的"读源码顺序"
ch05 已经讲清了 PartitionedParameterCoordinator 的语义。这里给一个最少行数的读源码路径——按顺序读,能完整理解 stage 3 一个 step 内 GPU 上的参数怎么动:
runtime/zero/partition_parameters.py:40–72—ZeROOrderedDict.__getitem__,看入口拦截;runtime/zero/parameter_offload.py:114—DeepSpeedZeRoOffload.__init__,注入这个 dict、构造 Coordinator;runtime/zero/partitioned_param_coordinator.py:44–50—ZeRoTraceMode枚举;runtime/zero/partitioned_param_coordinator.py:64–149—__init__与所有内部字段;runtime/zero/partitioned_param_coordinator.py:159–196—trace_prologue、状态切换逻辑;runtime/zero/stage3.py:136–250—DeepSpeedZeroOptimizer_Stage3.__init__,组装;runtime/zero/stage3.py内的backward / step实现 — 找reduce_partitioned_gradients、independent_gradient_partition_epilogue;- 最后回头看
runtime/engine.py:2351 / 2615 / 2790的forward / backward / step,理解上层包装。
读完这 8 步,你对 stage 3 的脑中模型应该和源码 1:1。
13.14 op_builder ↔ csrc 对照
每个 op 的 Python 编译脚本在 op_builder/,实际 C++/CUDA 源码在 csrc/。两者一一对应:
| op_builder/ | csrc/ | 用途 | DS_BUILD_ |
|---|---|---|---|
cpu_adam.py | adam/cpu_adam.cpp + adam/cpu_adam_impl.cpp | CPU offload 的 Adam(AVX-512) | CPU_ADAM |
fused_adam.py | adam/fused_adam_frontend.cpp + adam/multi_tensor_adam.cu | GPU fused Adam | FUSED_ADAM |
async_io.py | aio/(11 个文件,线程池 + libaio) | NVMe 异步 IO | AIO |
gds.py | gds/ | GPU-Direct Storage | GDS |
fused_lamb.py | lamb/ | FusedLamb(大 batch) | LAMB |
fused_lion.py | lion/ | FusedLion | LION |
quantizer.py | quantization/ | int8 / fp8 量化 | QUANTIZER |
fp_quantizer.py | fp_quantizer/ | 浮点量化 | FP_QUANTIZER |
transformer.py | transformer/ | v1 推理 fused transformer | TRANSFORMER |
transformer_inference.py | transformer/inference/ | v1 推理专用 kernel | TRANSFORMER_INFERENCE |
sparse_attn.py | sparse_attention/ | 已弃用 | — |
random_ltd.py | random_ltd/ | Random token dropping | — |
utils.py | utils/ | 通用 CUDA 工具 | UTILS |
注册中心:op_builder/all_ops.py:30 的 ALL_OPS = {op.name: op for op in __op_builders__}。新增 op 时往 __op_builders__ 里加自己的 builder 就会自动出现在 ds_report。
"自己加一个 op" 的步骤:
- 在
csrc/myop/写.cu+ pybind11 binding; - 在
op_builder/myop.py写一个MyOpBuilder(OpBuilder)子类,实现sources()、include_paths()、absolute_name(); - 在
op_builder/__init__.py把MyOpBuilder加进__op_builders__; - 在
deepspeed/ops/myop/__init__.py写 Python wrapper; - 跑
DS_BUILD_MYOP=1 pip install -e .编一次。ds_report里应该能看到myop ............... [YES] ...... [OKAY]。
13.15 2024–2026 新子系统源码地图
这些目录是新的,老书 / 老 blog 里不会提,但都已经在 master:
| 目录 / 文件 | 关键符号 (file:line) | 对应章节 |
|---|---|---|
deepspeed/runtime/superoffload/ | superoffload_stage3.py:27 SuperOffloadOptimizer_Stage3;superoffload_utils.py:19/38 IPC 协议 + worker 进程 | ch05.15 / ch06.10 |
deepspeed/runtime/zenflow/ | zenflow_config.py:12 ZenFlowConfig;zenflow_stage_1_and_2.py:47/82 基类 + factory | ch05.14 / ch12.12 |
deepspeed/runtime/zero/muon/ | muon_optimizer.py:14/26 MuonWithAuxAdam / step | ch07.15 / ch12.13 |
deepspeed/runtime/domino/ | async_linear.py:11 DominoAsyncColumnParallelLinear;transformer.py:34/50 HANDLE_DIC / NoOper | ch09.15 |
deepspeed/compile/ | backend.py:44/79/95 GraphOrder / register_compile_pass / launch_compile_passes;list_schedule.py pass 调度 | ch11.12 |
deepspeed/sequence/ | layer.py:19/93/111 _generate_layout_params / apply_rotary_pos_emb / uneven_heads_all2all;fpdt_layer.py 60 KB ALST 分块 attention;auto_sp.py 自动 SP 插入 | ch09.14 |
deepspeed/runtime/tensor_parallel/ | DS 原生 TP(与 AutoTP 配合) | ch09.13 |
deepspeed/inference/v2/ | engine_v2.py:30/107/158/184 InferenceEngineV2 / put / query / can_schedule;state_manager.py KV cache | ch10.10 |
13.16 跟着测试读 API
不知道一个新 feature 怎么用最快的方法:grep 它的测试。下面这几份测试堪称"API 教科书":
| 测试文件 | 示范了什么 |
|---|---|
tests/unit/runtime/zero/test_zero_context.py | deepspeed.zero.Init() context manager,模型加载时即按 ZeRO-3 切 |
tests/unit/runtime/zero/test_zero_leaf_module.py | 用 z3_leaf_module / z3_leaf_parameter 标注某些 module 不被 stage 3 切 |
tests/unit/runtime/zero/test_zeropp.py | ZeRO++ HPZ partition + 量化通信组合用法 |
tests/unit/runtime/zero/test_zero_tensor_fragment.py | 访问 stage 3 切片后参数的 .ds_tensor |
tests/unit/runtime/zero/test_offload_states.py | 动态 offload/reload 优化器状态、param(ch06.8 的运行时接口) |
tests/unit/ops/muon/test_muon.py | Muon 优化器最小调用 |
tests/unit/inference/test_inference.py | init_inference + kernel inject 的 e2e |
tests/unit/checkpoint/test_zero_optimizer.py | ZeRO checkpoint 保存恢复 |
读测试的好处:每个测试自带最小 config 与最小模型,不用先读上下游就能跑起来。怀疑某个 config 字段的真实行为时,去 tests/ 里 grep 字段名比看 doc 快。
13.17 zero_to_fp32.py 完整 CLI
这个脚本几乎是每个 DS 用户最终都会用一次的:把 ZeRO checkpoint 的多个 shard 合并成一份 PyTorch / HuggingFace 可加载的 fp32 / safetensors 权重。位置 deepspeed/utils/zero_to_fp32.py。完整签名:
python -m deepspeed.utils.zero_to_fp32 \
<checkpoint_dir> \ # ZeRO 保存的目录,里面有 global_step100/ 这种子目录
<output_dir> \ # 输出位置;得到 pytorch_model.bin 或 model.safetensors
[--max_shard_size 5GB] \ # HF shard 切分大小(保存超大模型时用)
[--safe_serialization] \ # 输出 safetensors 格式,不是 .bin
[--tag global_step100] \ # 选用哪个 step 的 checkpoint(默认最后一个)
[--exclude_frozen_parameters] \ # PEFT 场景下不导出冻结参数(只导 LoRA)
[-d] [--debug] # 多打日志
关键函数(同文件内):
convert_zero_checkpoint_to_fp32_state_dict()— 公开 API;返回标准 PyTorch state_dict;_get_fp32_state_dict_from_zero_checkpoint()— 主体逻辑;parse_optim_states()— 从 shard 里读 fp32 master weights。
下游加载:
# HF 模型加载
model = AutoModelForCausalLM.from_pretrained("output_dir/")
# 或者裸 PyTorch
state = torch.load("output_dir/pytorch_model.bin")
model.load_state_dict(state)
510ebe58e4e4 上是精确的;
DeepSpeed 高速演进,每隔 3-6 个月对照 CHANGELOG 翻新一遍是值得的。