2、常见显存杀手:Batch Size过大、序列长度过长、中间激活值爆炸、模型参数冗余

做深度学习训练,最怕什么?

我个人最怕的就是跑了大半天,突然弹出一行「CUDA out of memory」。嗯,那种感觉,就像你写代码写到一半电脑蓝屏一样酸爽。

今天咱们就来聊聊,到底是哪四个家伙把显存给吃光的。我这些年排查过的OOM案例,十有八九都能归到这几类里。

2.1 Batch Size过大——最直接的显存杀手

Batch Size(批大小)这东西,说白了就是一次往GPU里塞多少样本。你塞得越多,显存占得越狠。

为什么它会吃显存?

因为每个样本都要走一遍前向传播,都要在显存里留下自己的足迹。梯度、中间激活值,全都按Batch Size翻倍。

显存占用公式(简化版):

显存 ≈ Batch Size × (模型参数 + 中间激活值) × 精度字节数

我在项目中遇到过一位同事,把Batch Size从32调到128,想着「反正显存够大」。结果呢?跑了不到10步就OOM了。他忘了,显存占用是线性增长的,不是你想调就能调。

我的建议:

先从小Batch Size开始试,比如2或4。确认能跑通,再逐步往上加。别一上来就搞个128,那是给自己挖坑。

2.2 序列长度过长——Transformer的软肋

如果你用Transformer做NLP任务,序列长度绝对是显存大户。为什么?

因为自注意力机制的计算复杂度是 O(n²),n就是序列长度。长度翻倍,显存占用翻4倍。你想想看,这多恐怖。

举个例子:

  • 序列长度512,显存占用约2GB
  • 序列长度1024,显存占用约8GB
  • 序列长度2048,显存占用约32GB

我曾经在做一个长文档摘要项目时,序列长度设成了4096。结果一张A100直接爆掉。后来我改用滑动窗口+分段处理,才把问题解决。

避坑指南:

我曾经以为「显存够大就能随便加长序列」,结果被现实狠狠教育了一顿。序列长度超过1024时,一定要算好显存预算。

2.3 中间激活值爆炸——隐藏的显存黑洞

很多人只盯着模型参数看,觉得「参数越少,显存越省」。其实不然。

中间激活值(Intermediate Activations)才是真正的显存黑洞。每个Batch的每个样本,在每一层都会产生激活值。这些值在反向传播时要用,所以不能丢。

哪些操作会产生大量激活值?

  • 大卷积核(比如7×7)
  • 深层网络(比如ResNet-152)
  • 注意力头数过多
  • FFN中间层维度太大

我记得有一次排查一个ViT模型的OOM问题,模型参数才300M,但中间激活值占了6GB。嗯,这就是典型的「激活值爆炸」。

排查方法:

用 torch.cuda.memory_summary() 查看显存分配情况。如果发现大量「storages」来自中间张量,那就是激活值的问题。

2.4 模型参数冗余——不必要的显存浪费

最后一个杀手,是模型参数本身。但这里说的不是「模型太大」,而是「参数冗余」。

常见的冗余情况:

  • 全连接层维度设置过大(比如4096→4096,其实2048就够了)
  • 使用了不必要的偏置项(某些场景下可以去掉)
  • Embedding层词汇表太大(比如10万词,实际只用1万)
  • 重复的LayerNorm或BatchNorm

我见过一个项目,模型里塞了12个Transformer层,每层都有独立的LayerNorm。其实有些层可以共享归一化参数,能省下不少显存。

优化建议:

用 torchsummary 或 ptflops 分析模型参数分布。看看哪些层是「显存大头」,然后针对性优化。

知识体系总览

下面这张图,是我自己总结的显存杀手排查框架。你可以把它当成一个检查清单:

显存杀手排查框架 显存OOM Batch Size过大 序列长度过长 中间激活值爆炸 模型参数冗余 线性增长 梯度翻倍 激活值翻倍 O(n²)复杂度 注意力矩阵 滑动窗口 深层网络 大卷积核 注意力头数 全连接过大 词汇表冗余 重复归一化 排查优先级 1. 先看Batch Size(最容易调整) 2. 再看序列长度(Transformer项目重点) 3. 检查中间激活值(深层网络/大模型) 4. 最后优化模型参数冗余(长期优化)

快速排查表

为了方便你快速定位问题,我整理了一张排查表:

杀手类型 典型症状 排查方法 快速解决
Batch Size过大 小Batch能跑,大Batch就崩 逐步减小Batch Size测试 梯度累积
序列长度过长 长文本任务OOM 检查序列长度设置 滑动窗口/截断
中间激活值爆炸 模型参数小但显存占用大 torch.cuda.memory_summary() 梯度检查点
模型参数冗余 模型结构复杂但效果一般 torchsummary分析 剪枝/共享参数

最后提醒一句:

别一上来就怀疑是「显存不够」。先按上面四个方向排查一遍,很多时候问题出在代码或配置上,而不是硬件。

我曾经花了两天时间申请新显卡,结果发现只是Batch Size设大了。嗯,那种感觉,你懂的。

可可精品资料库