Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← 系统与高性能 / Systems & Performance

计算系统 / Computing Systems

1. 计算系统:计算机如何执行与加速程序

2. 从 C++ 源码到 CPU 执行

3. CPU 流水线、乱序执行与分支预测

4. Cache、一致性、伪共享与 NUMA

5. GPU、SM、Warp 与显存

6. 计算执行模型:程序怎样映射到机器

7. SIMD 与编译器向量化

8. C++ 多线程与 OpenMP

9. CUDA 平台与编程模型

10. CUDA Kernel、内存与性能

11. CPU-GPU 异构流水线

12. MPI 与分布式并行

13. 并行算法模式

14. 性能模型与工具

15. 递进学习项目:从单线程到集群

历史完整正文 / Original Deep Dives

1. 历史完整正文:统一前文章逐篇保留

原体系结构与硬件 / Original Architecture

1. 硬件编程与高性能计算:一张可走通的学习地图 / A Practical Learning Map for Hardware Programming and HPC

2. 计算机体系结构:CPU、内存与 GPU / Computer Architecture: CPUs, Memory, and GPUs

3. 计算机架构基础——为什么 GPU 比 CPU 更快 / Computer Architecture Fundamentals: Why GPUs Outperform CPUs

4. 并行计算理论——30 天训练能优化到多快? / Parallel Computing Theory and the Limits of Training Acceleration

5. GPU 架构深入——上万个核心如何分工协作 / GPU Architecture and Massive Parallel Execution

6. CUDA 编程模型——把矩阵乘法映射到 GPU / The CUDA Programming Model for Mapping Matrix Multiplication to GPUs

7. CUDA 内存管理——百亿参数如何装进显存 / CUDA Memory Management for Large Models

8. CUDA 性能优化——从 30 天缩短到 10 天 / CUDA Performance Optimization

9. CPU 并行编程——OpenMP 与 SIMD 向量化 / CPU Parallel Programming with OpenMP and SIMD

10. HPC 集群与 MPI——多节点分布式训练 / HPC Clusters and MPI for Distributed Training

11. 异构计算——CPU 与 GPU 如何协同工作 / Heterogeneous Computing with CPUs and GPUs

12. 深度学习训练优化实战——从 30 天到 3 天 / Deep Learning Training Optimization from Thirty Days to Three

13. 性能分析工具——找到真正的瓶颈 / Performance Analysis Tools for Finding Real Bottlenecks

14. NPU 全景——昇腾/寒武纪/TPU/苹果生态 / The NPU Landscape: Ascend, Cambricon, TPU, and Apple

15. 未来趋势——2030 年的计算机会是什么形态 / Future Computing Trends Toward 2030

16. 硬件与高性能计算:从“程序为什么慢”开始 / Hardware and HPC Starting from Why Programs Are Slow

原并行计算 / Original Parallel Computing

1. 并行计算:从 SIMD 到 MPI / Parallel Computing from SIMD to MPI

2. 并行计算全景:从晶体管、CPU、GPU 到计算集群 / Parallel Computing from Transistors, CPUs, and GPUs to Clusters

3. 并行计算基础:任务分解、加速比与可扩展性 / Parallel Computing Fundamentals: Decomposition, Speedup, and Scalability

4. 处理器体系结构:从指令流水线到多核芯片 / Processor Architecture from Instruction Pipelines to Multicore Chips

5. CPU 并行:多线程、SIMD、Cache 一致性与 NUMA / CPU Parallelism with Threads, SIMD, Cache Coherence, and NUMA

6. 内存层次:Cache、带宽、局部性与一致性 / Memory Hierarchies, Bandwidth, Locality, and Coherence

7. GPU 体系结构:SIMT、Warp、SM 与吞吐优先设计 / GPU Architecture with SIMT, Warps, and Streaming Multiprocessors

8. CUDA 编程模型:Thread、Block、Grid 与内存协作 / CUDA Threads, Blocks, Grids, and Cooperative Memory Access

9. 并行算法模式:Map、Reduce、Scan、Stencil 与任务图 / Parallel Patterns: Map, Reduce, Scan, Stencil, and Task Graphs

10. 异构计算:CPU、GPU、NPU 如何协同工作 / Heterogeneous Computing with CPUs, GPUs, and NPUs

11. 分布式并行:MPI、集合通信、RDMA 与多机多卡 / Distributed Parallelism with MPI, Collective Communication, and RDMA

12. 性能工程:测量、Roofline、瓶颈定位与优化闭环 / Performance Engineering with Measurement, Roofline, and Bottleneck Analysis

13. 并行计算实战:AI、CAE、图像与科学计算 / Parallel Computing for AI, CAE, Imaging, and Scientific Computing

14. 并行计算实践路线:从单核优化到多机多卡 / A Parallel Computing Project Path from Single-Core to Multi-Node GPUs

本页目录

深度学习训练优化实战——从 30 天到 3 天 / Deep Learning Training Optimization from Thirty Days to Three ​

📅 创建时间:2026-06-02 🏷️ 标签:#DL #训练优化 #混合精度 #GradientAccumulation #DeepSpeed #ZeRO 📚 前置知识:[[08-mpi-cluster-hpc]](分布式训练) [[06-cuda-optimization]](CUDA 优化) 📚 相关知识:[[/04-ai/01-llm-engineering/09-transformer-training-computation]](训练计算详解) [[/04-ai/01-llm-engineering/13-training-infrastructure]](训练基础设施)


先抓住直觉 ​

训练优化是在速度、显存和数值稳定性之间做交换:混合精度减少字节数,梯度累积用更多步骤模拟大批量,Checkpointing 用重复计算换显存,ZeRO 把冗余状态分散到多张卡。

  • 必须理解:每种技术省下的是什么、额外付出的是什么。
  • 用到再查:PyTorch/DeepSpeed 配置字段和具体 API。
  • 避免误区:这些收益不能简单相乘,最终效果取决于实际瓶颈和通信开销。

场景:你的训练为什么跑得比预期慢? ​

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  你的训练配置:                                            │
│  - 模型:175B 参数                                         │
│  - 硬件:8 × A100 80GB                                   │
│  - batch size:8(每卡)                                  │
│  - 精度:FP32                                             │
│  - 优化器:Adam                                           │
│  - 预计时间:90 天                                        │
│                                                             │
│  同行竞争者的配置:                                        │
│  - 模型:175B 参数                                         │
│  - 硬件:8 × A100 80GB                                   │
│  - batch size:16(每卡)+ 梯度累积 8                     │
│  - 精度:FP16(混合精度)                                 │
│  - 优化器:Adam + DeepSpeed ZeRO-3                       │
│  - 预计时间:3 天                                         │
│                                                             │
│  差距在哪里?本章告诉你。                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

第1节:混合精度训练——显存减半,速度翻倍 ​

为什么需要混合精度? ​

FP32(32位浮点):
- 存储:4 字节/参数
- 计算:单精度
- 显存占用:高
- 速度:慢

FP16(16位浮点):
- 存储:2 字节/参数
- 计算:半精度
- 显存占用:FP32 的一半
- 速度:Tensor Core 快 8-32 倍

但 FP16 有精度问题:
- 表示范围小:FP16 max = 65504,FP32 max = 3.4e38
- 大模型训练中,梯度可能超出 FP16 表示范围

解决方案:混合精度训练
- Forward/Backward:FP16(快、省显存)
- Optimizer states:FP32(高精度)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

混合精度训练流程 ​

┌─────────────────────────────────────────────────────────────┐
│                    混合精度训练流程                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Forward(FP16):                                         │
│  1. 权重备份 FP32 → FP16                                 │
│  2. FP16 前向传播 → loss                                 │
│  3. Loss 缩放(loss scaling,防止下溢)                    │
│                                                             │
│  Backward(FP16):                                       │
│  4. FP16 反向传播 → 梯度                                 │
│  5. Unscale 梯度                                          │
│                                                             │
│  Optimizer(FP32):                                      │
│  6. 梯度 FP16 → FP32(精度恢复)                         │
│  7. FP32 优化器更新 → FP32 权重                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

PyTorch 混合精度实现 ​

python
from torch.cuda.amp import autocast, GradScaler

# 训练循环
scaler = GradScaler()  # Loss 缩放器

for batch in dataloader:
    optimizer.zero_grad()

    # Forward(自动用 FP16)
    with autocast():
        output = model(batch.input)
        loss = criterion(output, batch.target)

    # Backward(自动处理缩放)
    scaler.scale(loss).backward()

    # Optimizer step
    scaler.step(optimizer)
    scaler.update()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

显存节省计算 ​

┌─────────────────────────────────────────────────────────────┐
│                    混合精度显存节省                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  FP32 训练(单卡,175B 模型):                            │
│  参数:700 GB                                             │
│  梯度:700 GB                                             │
│  优化器状态(Adam):1400 GB(2×FP32)                   │
│  激活值:~200 GB                                          │
│  总计:~3000 GB ≈ 需要 38 张 A100(80GB)               │
│                                                             │
│  FP16 混合精度训练(单卡):                               │
│  参数(FP16):350 GB                                      │
│  梯度(FP16):350 GB                                     │
│  优化器状态(FP32):1400 GB                              │
│  激活值(FP16):~100 GB                                  │
│  总计:~2200 GB ≈ 需要 28 张 A100(80GB)               │
│                                                             │
│  节省:显存减少约 25%                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

第2节:梯度累积——模拟更大 batch size ​

为什么需要梯度累积? ​

问题:单卡显存有限,无法使用大 batch size

例如:
- 单卡最大 batch size = 4(显存刚好够)
- 有效 batch size = 4(太小,训练不稳定)

解决方案:梯度累积
- 累积多个小 batch 的梯度
- 累积够一个"虚拟"大 batch 后,再更新参数
1
2
3
4
5
6
7
8
9

梯度累积原理 ​

python
# 梯度累积示例
effective_batch_size = 32  # 想要的有效 batch size
micro_batch_size = 4       # 实际能装的 batch size
accumulation_steps = effective_batch_size // micro_batch_size  # = 8

optimizer.zero_grad()

for i in range(accumulation_steps):
    batch = dataloader[i]  # micro batch

    # Forward
    with autocast():
        output = model(batch)
        loss = criterion(output, batch.target)

    # Backward(只累积梯度,不更新参数)
    scaler.scale(loss).backward()

    # 每 accumulation_steps 步才更新一次
    if (i + 1) % accumulation_steps == 0:
        scaler.step(optimizer)
        scaler.update()
        optimizer.zero_grad()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

梯度累积 + 混合精度 ​

python
# 完整的训练步骤
scaler = GradScaler()

for epoch in range(num_epochs):
    for step, batch in enumerate(dataloader):
        with autocast():
            output = model(batch.input)
            loss = criterion(output, batch.target) / accumulation_steps

        scaler.scale(loss).backward()

        if (step + 1) % accumulation_steps == 0:
            scaler.unscale_(optimizer)

            # 梯度裁剪(避免梯度爆炸)
            torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)

            scaler.step(optimizer)
            scaler.update()
            optimizer.zero_grad()

            # 学习率调度
            scheduler.step()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

第3节:Activation Checkpointing——用时间换显存 ​

原理 ​

问题:训练 Transformer 时,中间激活值占用大量显存

以 175B 模型为例:
- 序列长度:2048
- 隐藏维度:12288
- 层数:96
- 激活值显存 ≈ 96 × 2048 × 12288 × 2B × 2(反向)≈ 100 GB

解决:Activation Checkpointing(梯度检查点)
- 不保存所有激活值
- 只保存每 N 层的输出
- 反向传播时重新计算被丢弃的激活值
1
2
3
4
5
6
7
8
9
10
11
12
python
# PyTorch Activation Checkpointing
from torch.utils.checkpoint import checkpoint

class TransformerLayer(torch.nn.Module):
    def forward(self, x):
        # Forward 时,不保存中间激活值
        x = checkpoint(self.attention, x)
        x = checkpoint(self.feed_forward, x)
        return x

# 或者对整个模型应用
model = torch.utils.checkpoint.checkpoint_sequential(
    layers,  # 模型的各层
    checkpoint_segments=8,  # 分成 8 段
    input
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

时间 vs 显存 trade-off ​

┌─────────────────────────────────────────────────────────────┐
│                    Checkpointing 效果                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  175B 模型训练:                                           │
│                                                             │
│  无 Checkpoint:                                           │
│  激活值显存:~100 GB                                      │
│  显存总计:~450 GB/卡                                     │
│  需要:6 张 A100(80GB)                                   │
│                                                             │
│  每 12 层一个 checkpoint:                                 │
│  激活值显存:~100/12 ≈ 8 GB                              │
│  显存总计:~360 GB/卡                                     │
│  需要:5 张 A100(80GB)                                   │
│  时间增加:约 30%(重新计算激活值)                        │
│                                                             │
│  每 24 层一个 checkpoint:                                 │
│  激活值显存:~100/24 ≈ 4 GB                              │
│  显存总计:~356 GB/卡                                     │
│  需要:5 张 A100(80GB)                                   │
│  时间增加:约 40%                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

第4节:DeepSpeed ZeRO——超越数据并行 ​

ZeRO 三级分片 ​

┌─────────────────────────────────────────────────────────────┐
│                    ZeRO 分片策略                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ZeRO-1(优化器状态分片):                               │
│  每个 GPU 只保存 1/N 的优化器状态                         │
│  显存节省:4 倍                                           │
│  通信量:不增加                                           │
│                                                             │
│  ZeRO-2(梯度分片):                                     │
│  每个 GPU 只保存 1/N 的梯度                               │
│  显存节省:2 倍(叠加后 8 倍)                           │
│  通信量:略微增加                                         │
│                                                             │
│  ZeRO-3(参数分片):                                     │
│  每个 GPU 只保存 1/N 的参数                               │
│  显存节省:N 倍(理论上无限扩展)                        │
│  通信量:显著增加                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

ZeRO-3 配置示例 ​

python
# deepspeed_config.json
{
    "zero_optimization": {
        "stage": 3,  # ZeRO-3
        "stage3_param_persistence_threshold": 1e4,
        "stage3_gather_16bit_weights_on_model_save": True,
        "contiguous_gradients": True
    },
    "fp16": {
        "enabled": True,
        "loss_scale": 0,
        "loss_scale_window": 1000,
        "initial_scale_power": 16
    },
    "gradient_clipping": 1.0
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
python
# train.py
import deepspeed

# 模型
model = TransformerModel()

# DeepSpeed 初始化
model_engine, optimizer, _, _ = deepspeed.initialize(
    model=model,
    config="deepspeed_config.json",
    training_data=train_dataset
)

# 训练循环
for batch in dataloader:
    loss = model_engine(batch.input, batch.target)
    model_engine.backward(loss)
    model_engine.step()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

第5节:完整训练配置示例 ​

┌─────────────────────────────────────────────────────────────┐
│                    175B 模型训练配置                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  硬件:64 × A100 80GB(8 节点 × 8 卡)                   │
│                                                             │
│  优化策略叠加:                                           │
│  1. 混合精度(FP16 Forward/Backward + FP32 Optimizer)      │
│  2. 梯度累积(effective batch = 4096)                    │
│  3. Activation Checkpointing(每 24 层一个 checkpoint)     │
│  4. DeepSpeed ZeRO-3(参数/梯度/优化器状态分片)            │
│  5. 流水线并行(8 个 stage)                              │
│                                                             │
│  显存使用(每卡):                                       │
│  参数(FP16):350/64 ≈ 5.5 GB                          │
│  梯度(FP16):350/64 ≈ 5.5 GB                          │
│  优化器状态(FP32):1400/64 ≈ 22 GB                     │
│  激活值(FP16):~30 GB(checkpoint 后)                  │
│  总计:~63 GB/卡 < 80 GB ✅                              │
│                                                             │
│  训练时间:                                               │
│  理论 TFLOPS 利用率:约 50%                              │
│  预计训练时间:~3 天                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

升华:优化策略叠加效果 ​

┌─────────────────────────────────────────────────────────────┐
│                    30 天 → 3 天优化路径                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  基准:单卡 FP32,batch=1                                 │
│  时间:30 天                                              │
│                                                             │
│  第1步:FP16 混合精度 → 时间 ÷ 2 = 15 天              │
│  第2步:梯度累积(batch×8)→ 时间 ÷ 1.5 = 10 天     │
│  第3步:Activation Checkpointing → 时间 × 1.3 = 13 天  │
│  第4步:8 卡数据并行(ZeRO-3)→ 时间 ÷ 6 = 2.2 天   │
│  第5步:流水线并行(8 stage)→ 时间 ÷ 1.2 = 1.8 天  │
│                                                             │
│  实际效果:约 3 天                                       │
│                                                             │
│  关键:多种优化策略叠加,而不是单一优化                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

"AI 可查 vs 必须理解"清单 ​

AI 可查:
✅ PyTorch AMP 的具体 API(GradScaler 参数)
✅ DeepSpeed ZeRO 的具体配置参数
✅ Activation Checkpointing 的具体函数

必须理解:
🔴 混合精度:Forward/Backward 用 FP16,Optimizer 用 FP32
🔴 梯度累积:用小 batch 模拟大 batch,不增加显存
🔴 Activation Checkpointing:用计算时间换显存
🔴 ZeRO 三级分片:优化器状态 → 梯度 → 参数
🔴 多种优化策略叠加 = 显存大幅减少 + 时间可接受
1
2
3
4
5
6
7
8
9
10
11

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇11. 异构计算——CPU 与 GPU 如何协同工作 / Heterogeneous Computing with CPUs and GPUs
下一篇13. 性能分析工具——找到真正的瓶颈 / Performance Analysis Tools for Finding Real Bottlenecks

持续记录,持续成长

Copyright © Tidenflow