共计 940 个字符,预计需要花费 3 分钟才能阅读完成。
数学原理与计算图解析
反向传播的核心是链式法则的微分原理。给定复合函数 $y=f(g(x))$,其导数可表示为:
$$\frac{dy}{dx} = \frac{dy}{dg} \cdot \frac{dg}{dx}$$
在计算图中,这个过程的实现分为三个阶段:
- 前向传播:构建计算图并保存中间结果
- 反向传播:从输出层开始按拓扑逆序计算梯度
- 参数更新:根据梯度下降算法调整权重
显存瓶颈与优化方案
痛点分析
- 显存爆炸:中间变量随网络深度线性增长
- 重复计算:非叶子节点的中间结果被多次使用

关键技术实现
梯度检查点技术
通过选择性丢弃中间结果,在反向传播时重新计算:
- 将网络划分为若干段(Segment)
- 前向时只保留分段边界处的激活值
- 反向时按需重新计算该段内的中间结果
动态规划策略
- 内存复用:预分配固定大小的显存池
- 生命周期管理:标记张量的可释放时间点
PyTorch 工程实践
自定义 Autograd Function
class MemoryEfficientFunction(torch.autograd.Function):
@staticmethod
def forward(ctx, input):
ctx.save_for_backward(input) # 选择性保存
# ... 前向计算逻辑
@staticmethod
def backward(ctx, grad_output):
input, = ctx.saved_tensors # 按需恢复
# ... 基于检查点的重计算
检查点 API 使用
# 将 ResNet 块包裹为检查点
blocks = [torch.utils.checkpoint.checkpoint(resnet_block, x)
for x in range(num_blocks)
]
避坑指南
- 并发冲突:
- 数据并行下需确保检查点段与设备对齐
-
避免在 DataLoader workers 内使用检查点
-
混合精度训练:
- 检查点重计算需保持与原始相同的精度
- 建议使用
torch.cuda.amp自动管理
开放性问题
针对 Transformer 结构的优化方向:
- 注意力机制的梯度计算能否分段进行?
- 如何平衡重计算开销与显存节省?
- 能否开发层间共享的梯度计算策略?
(附:实际测试中 V100 显卡的 torch.profiler 火焰图分析显示,优化后反向传播时间增加 15%,但显存峰值下降 34%)
正文完
