大模型分布式训练有关知识
一、总框架
大模型分布式技术主要解决两个问题:
- 模型放不下:一张GPU显存不足
- 训练速度慢:一张GPU计算能力不足
不同技术解决的问题不同:

二、一个模型到底是怎么训练的
假设模型看到一句话:
输入:我今天去学校
目标:预测下一个Token
一次训练经过四步。
1、前向传播 Forward
数据经过模型:
输入Token
↓
Embedding
↓
Transformer第1层
↓
Transformer第2层
↓
输出概率
模型根据当前参数计算预测结果。
例如:
模型预测:“我今天去公园”
正确答案:“我今天去学校”
2、计算损失Loss
Loss衡量预测结果与正确答案相差多少:
预测越准确 → Loss越小
预测越错误 → Loss越大
3、反向传播 Backward
反向传播计算:
每一个参数应该往哪个方向调整,才能让Loss下降?
这个调整方向叫梯度 Gradient。
假设一个参数当前是:
w = 0.5
反向传播算出:
gradient = 0.1
表示增大这个参数可能让Loss升高,因此优化器会尝试减小它。
4、优化器更新参数
最简单的更新形式是:
新参数 = 旧参数 - 学习率 × 梯度
不断重复这个过程,模型就逐渐学习到了数据规律。
三、训练为什么需要那么多显存
训练至少保存四类数据:
1、模型参数 Parameters
模型真正学习的内容,例如:
Embedding权重
Attention权重
MLP权重
LayerNorm参数
如果模型有10亿参数,即1B参数,使用FP16保存:
1B × 2字节 ≈ 2GB
这只是模型权重。
2、梯度 Gradients
每一个需要训练的参数通常都需要对应的梯度。
参数:w
梯度:dw
如果参数需要约2GB,FP16梯度也可能再占约2GB
3. 优化器状态 Optimizer States
Adam优化器不只保存参数,还会为参数维护一阶、二阶动量等状态。
简单理解:
参数
梯度
历史平均梯度
历史平方梯度
可能还有FP32参数副本
所以一个“参数权重只有2GB”的模型,完整训练可能需要十几GB甚至更多显存。
4. 激活值 Activations
前向传播时,每层产生的中间结果需要暂时保存,因为反向传播还要使用。
激活值通常受到以下因素影响:
Batch Size
序列长度
隐藏层大小
Transformer层数
所以序列越长、Batch越大,训练显存通常越高。
最终可以记成:
训练显存
≈ 模型参数
+ 梯度
+ 优化器状态
+ 激活值
+ 临时计算空间
这就是ZeRO存在的根本原因:它主要切分前三类模型训练状态。
四、什么是分布式训练
分布式训练就是:
让多个计算进程、多个GPU甚至多台机器共同完成一次模型训练。
例如有两张GPU:
GPU 0
GPU 1
但有两张GPU,不代表显存会自动合并。
假设每张卡24GB:
错误理解:两张卡自动变成48GB显存
实际上默认情况下:
GPU 0有自己的24GB
GPU 1有自己的24GB
两张卡拥有独立显存。只有把模型或训练状态主动切分,才能利用两张卡共同承载一个更大的模型。
因此,多GPU训练的核心是两个动作:
切分
通信
先决定把什么切开,再决定GPU之间如何交换数据。
五、分布式训练中的基础名词
假设一台服务器有两张GPU,通常启动两个训练进程:
进程0 → GPU 0
进程1 → GPU 1
Process
Process就是操作系统中的训练进程。
分布式GPU训练通常采用:
一张GPU对应一个进程
Rank
每个进程的全局编号。
双卡时:
进程0:rank = 0
进程1:rank = 1
rank 0通常负责打印日志、汇总结果,但它不代表性能更强。
World Size
总进程数量。
双卡单机通常是:
world_size = 2
四卡则是:
world_size = 4
Local Rank
当前机器上的进程编号。
单机双卡:
local_rank 0 → GPU 0
local_rank 1 → GPU 1
多机训练时,rank和local rank不一定相同。
六、数据并行 DDP
数据并行的核心是:
每张GPU保存一个完整模型,但处理不同的数据。
假设原始Batch有8条数据,两张GPU可以这样分:
GPU 0:完整模型 + 前4条数据
GPU 1:完整模型 + 后4条数据
具体流程如下:

为什么需要同步梯度
GPU 0看到了数据A,得到梯度:
g0
GPU 1看到了数据B,得到梯度:
g1
如果它们直接更新参数:
GPU 0使用g0更新
GPU 1使用g1更新
两份模型就会逐渐变得不同。
所以DDP会计算平均梯度:
g = (g0 + g1) / 2
然后两张卡都使用相同的 g 更新参数。这样两份模型仍然保持一致。
All-Reduce是什么
All-Reduce是一种集合通信操作。
可以把它理解成:
收集所有GPU的梯度
→ 求和或求平均
→ 把结果发回所有GPU
DDP的主要通信成本就来自梯度All-Reduce。
DDP解决什么问题
DDP主要提高训练吞吐:
一张卡一次处理4条
两张卡一次共处理8条
但它不能显著解决模型本身放不下的问题,因为每张卡仍保存完整模型、完整梯度和完整优化器状态。
例如模型训练需要30GB:
GPU 0:需要30GB
GPU 1:也需要30GB
即使两张GPU分别有24GB,DDP仍然会OOM。
全局Batch Size
DDP中:
全局Batch
= 每卡Batch
× 数据并行GPU数
× 梯度累积次数
例如:
每卡Batch = 4
GPU数 = 2
梯度累积 = 2
全局Batch = 4 × 2 × 2 = 16
DataParallel和DistributedDataParallel的区别
“数据并行”是一个思想。
PyTorch中有两个容易混淆的类:
DataParallel:旧的单进程多卡方式。DistributedDataParallel,简称DDP:多进程多卡方式。
实际学习应该重点学习DDP。
七、ZeRO是什么
ZeRO全称是:
Zero Redundancy Optimizer
可以理解为:
消除数据并行中重复保存的训练状态。
DDP哪里存在重复
两张GPU进行DDP时:
GPU 0:
完整参数
完整梯度
完整优化器状态
GPU 1:
完整参数
完整梯度
完整优化器状态
两张卡保存了大量重复内容。
ZeRO认为:
既然GPU之间能够通信,就没必要让每张卡长期保存所有训练状态。
ZeRO-1
切分优化器状态:
GPU 0:保存一半优化器状态
GPU 1:保存另一半优化器状态
但是每张卡仍保存完整:
模型参数
梯度
ZeRO-2
继续切分梯度:
GPU 0:一半优化器状态 + 一半梯度
GPU 1:另一半优化器状态 + 另一半梯度
每张卡仍保存完整模型参数。
ZeRO-3
继续切分模型参数:
GPU 0:一半参数 + 一半梯度 + 一半优化器状态
GPU 1:另一半参数 + 另一半梯度 + 另一半优化器状态
参数切开后怎么计算
这是ZeRO-3最关键的底层问题。
某张GPU计算某一层时,需要这一层的完整参数。于是ZeRO-3会:
计算前:从其他GPU收集当前层需要的参数
计算中:使用完整的当前层参数
计算后:重新释放或分片这些参数
所以ZeRO-3可以大幅节省显存,但会增加参数收集通信。
因此:
ZeRO级别越高
通常越省显存
但通信和管理成本也可能越高
ZeRO的目标首先是“让模型能够训练”,而不是保证“训练一定更快”。
八、模型并行是什么
模型并行不是某一种具体技术,而是一大类方法:
一个模型太大或计算量太高,把模型本身拆到多张GPU上共同完成一次前向和反向传播。
它与数据并行最大的区别是:
数据并行:每张GPU都有完整模型,切分数据。
模型并行:一个模型分布在多张GPU上,GPU共同处理数据。
模型并行主要包括:

1、为什么需要模型并行
假设模型完整训练需要40GB显存,但你有两张32GB GPU。
如果使用数据并行DDP:
GPU 0:保存完整40GB模型状态 → OOM
GPU 1:保存完整40GB模型状态 → OOM
DDP不会自动合并两张卡的显存,因为每张GPU都需要保存完整模型。
模型并行则会尝试拆开模型:
GPU 0:保存模型的一部分
GPU 1:保存模型的另一部分
这样单张GPU只需要承担部分模型。
模型并行主要解决:
- 一个模型放不进单卡;
- 模型的一层放不进单卡;
- 单卡计算速度不够;
- 推理时希望多张GPU共同降低延迟。
2、张量并行 TP
张量并行的核心是:
把同一个神经网络层中的大矩阵拆到多张GPU上计算。
它也叫层内并行 Intra-layer Parallelism。
1. 从线性层理解
Transformer中大量计算都是矩阵乘法。假设一个线性层:
Y = XW
其中:
X:输入
W:模型权重
Y:输出
如果权重矩阵 W 很大,可以把它拆到两张GPU。
2. 按列切分
将权重矩阵按输出维度拆开:
W = [W₀, W₁]
GPU分别计算:
GPU 0:Y₀ = XW₀
GPU 1:Y₁ = XW₁
最后拼接:
Y = [Y₀, Y₁]
过程如下:

每张GPU只保存部分权重,也只计算部分输出。
这种方式通常叫:
Column Parallel
列并行
3. 按行切分
也可以把输入和权重按输入维度拆开:
X = [X₀, X₁]
W = [W₀
W₁]
GPU分别计算:
GPU 0:Y₀ = X₀W₀
GPU 1:Y₁ = X₁W₁
完整结果是:
Y = Y₀ + Y₁
所以需要All-Reduce求和:

这种方式叫:
Row Parallel
行并行
4. Transformer里怎么切
一个Transformer层主要包括:
Attention
MLP
LayerNorm
残差连接
Attention切分
假设模型有16个Attention Head,使用TP=2:
GPU 0:负责Head 0~7
GPU 1:负责Head 8~15
每张卡只计算一半注意力头,然后通过通信合并结果。
所以通常要求:
Attention Head数量能够被TP数量整除
例如:
16个Head,TP=2:可以
16个Head,TP=4:可以
16个Head,TP=3:通常不可以
MLP切分
Transformer的MLP通常包含:
隐藏维度
→ 扩展维度
→ 激活函数
→ 恢复隐藏维度
假设:
hidden_size = 4096
intermediate_size = 11008
可以让:
GPU 0:负责一部分intermediate维度
GPU 1:负责另一部分intermediate维度
最后再通过All-Reduce合并。
5. TP为什么通信频繁
Transformer每一层都需要多张GPU共同计算:
第1层:GPU通信
第2层:GPU通信
第3层:GPU通信
……
第32层:GPU通信
因此TP非常依赖GPU之间的通信速度。
如果计算时间是:
每层计算:5毫秒
每层通信:1毫秒
影响不算太大。
如果模型很小:
每层计算:0.5毫秒
每层通信:1毫秒
那么双卡可能比单卡还慢。
这也是为什么:
张量并行主要用于大模型,而不是卡越多就越快。
6. TP解决什么问题
TP适合:
- 一个Transformer层太大,单卡放不下;
- 模型推理权重放不进单卡;
- 希望多张GPU共同完成一次推理;
- GPU之间具有较快连接。
TP的优点:
- 分摊单层参数;
- 分摊单层计算;
- 可以降低单卡模型权重显存;
- 大模型推理时可能降低延迟。
TP的缺点:
- 几乎每层都需要通信;
- 强依赖卡间带宽;
- 模型维度需要满足切分条件;
- 实现和Checkpoint管理较复杂。
3、流水线并行 PP
流水线并行的核心是:
按层切分模型,不同GPU负责不同层。
它也叫层间并行 Inter-layer Parallelism。
假设模型有12层,两张GPU:
GPU 0:Embedding + 第1~6层
GPU 1:第7~12层 + LM Head
训练数据流动过程:
前向传播
数据首先进入GPU 0:
输入
↓
GPU 0执行第1~6层
↓ 传递中间激活值
GPU 1执行第7~12层
↓
输出
GPU之间传递的不是完整模型参数,而是中间激活值。
反向传播则反过来:
GPU 1:计算第7~12层梯度
↓ 发送激活梯度
GPU 0:计算第1~6层梯度
所以PP主要通信:
前向:激活值
反向:激活值对应的梯度
TP主要在层内部频繁通信,而PP主要在流水线阶段边界通信。
流水线为什么会浪费时间
如果只有一个Batch:
时间1:GPU 0工作,GPU 1等待
时间2:GPU 1工作,GPU 0等待
这虽然解决了显存问题,却没有很好地并行计算。
因此需要Micro Batch。
Micro Batch
把一个Batch切成多个Micro Batch:
Micro Batch 1
Micro Batch 2
Micro Batch 3
Micro Batch 4
形成类似工厂流水线:
时刻1:GPU 0处理微批次1
时刻2:GPU 0处理微批次2,GPU 1处理微批次1
时刻3:GPU 0处理微批次3,GPU 1处理微批次2
流水线气泡
开始和结束阶段仍然会有GPU处于等待状态,这段空闲就叫流水线气泡。
假设:
流水线阶段数 = p
Micro Batch数量 = m
在简单调度下,流水线利用率可以粗略理解为:
利用率 ≈ m / (m + p - 1)
例如2个阶段:
m = 1:利用率约 1/2
m = 4:利用率约 4/5
m = 16:利用率约 16/17
Micro Batch越多,流水线利用率提高。
但Micro Batch增加也会影响调度、显存和优化过程。
PP的另一个难点:负载均衡
如果:
GPU 0负责的层计算需要1秒
GPU 1负责的层计算需要3秒
GPU 0完成后仍然要等待GPU 1。
所以不能只按“层数相等”切分,还要考虑:
每层参数量
每层计算量
激活值大小
通信数据量
......
九、TP和PP的核心区别
| 对比 | 张量并行TP | 流水线并行PP |
| 切分位置 | 同一层的内部 | 不同模型层 |
| 又叫 | 层内并行 | 层间并行 |
| 每张GPU保存 | 每层的一部分 | 一部分完整层 |
| 前向计算 | 多张卡共同计算同一层 | 数据依次经过不同GPU |
| 主要通信 | All-Reduce、All-Gather | 激活值、梯度 |
| 通信频率 | 基本每层都通信 | 阶段边界通信 |
| 主要问题 | 通信开销大 | 流水线气泡 |
| 关键要求 | 模型维度可切分 | 各阶段负载均衡 |
| 适用场景 | 单层太大 | 模型层数多、整体太大 |
十、模型并行与ZeRO-3的区别
ZeRO-3也会切分模型参数,但它和TP仍然不同。
ZeRO-3
ZeRO-3主要切分的是参数存储:
GPU 0长期保存一部分参数
GPU 1长期保存另一部分参数
计算某一层前,再临时收集该层参数。
每个数据并行进程仍然处理自己的数据,并执行完整层计算。
核心目标是:
减少重复存储
TP
TP不仅切分参数存储,也切分矩阵计算:
GPU 0计算矩阵的一部分
GPU 1计算矩阵的另一部分
核心目标是:
分摊单层存储和单层计算
因此:
| 对比 | ZeRO-3 | TP |
| 主要切分 | 存储训练状态 | 层内参数和计算 |
| 计算前 | 收集当前层参数 | 不需要每卡拥有完整矩阵 |
| 每张卡处理的数据 | 通常不同 | 通常共同处理同一批输入 |
| 主要目的 | 省训练显存 | 单层跨卡计算 |
| 通信 | 参数收集、梯度分片 | 层内All-Reduce/All-Gather |
一句话:
ZeRO-3更像“分开保管,使用时临时收集”;TP更像“共同计算,每人完成一部分”。
十一、什么时候选择哪一种技术
情况1:模型能放入单卡,只是训练慢
选择:
DDP
情况2:模型参数能放入单卡,但优化器、梯度让训练OOM
选择:
ZeRO-1/2/3
情况3:模型的一层就放不进单卡
选择:
TP
情况4:每个层都能放进单卡,但完整模型放不下
选择:
PP
或ZeRO-3
情况5:模型非常大,多种方法单独使用都不够
选择:
DP + TP + PP
在多节点集群中通常倾向于:
节点内部高速互联:TP
节点之间:PP或DP
因为TP通信频率最高,应尽量放在通信最快的GPU组中。
更多推荐

所有评论(0)