一、显存溢出初探:什么是显存溢出?

显存溢出,说白了就是 GPU 的「内存」不够用了。

你想想看,深度学习训练时,模型参数、梯度、优化器状态、中间激活值……这些东西全都要塞进显存里。一旦总需求超过了 GPU 的物理显存容量,就会触发 CUDA out of memory 错误。

我个人习惯把显存比作一个「临时仓库」。训练时,数据进来、计算完、再出去,仓库里的货物不断流转。但如果货物太多,仓库装不下,那就只能报错了。

为什么深度学习训练中容易遇到?

这个问题我经常被问到。其实原因很直接:

  • 模型越来越大:从几百万参数到几十亿参数,显存需求是指数级增长的
  • 批量大小(batch size)太贪心:很多人一上来就设 64、128,结果显存直接爆掉
  • 中间激活值被忽略:我见过不少新手,只算了模型参数的大小,忘了算前向传播时每一层的激活值——这些才是吃显存的大头
  • 混合精度没用好:FP32 和 FP16 混着用,有时候反而让显存碎片化更严重

核心结论:显存溢出不是「模型太大」这一个原因,而是多个因素叠加的结果。定位问题,得一个一个拆。

常见报错信息解读

CUDA out of memory 的报错,其实藏着不少信息。我教你怎么看。

RuntimeError: CUDA out of memory. Tried to allocate 2.00 GiB 
(GPU 0; 8.00 GiB total capacity; 6.32 GiB already allocated; 
1.12 GiB free; 4.78 GiB reserved in total by PyTorch)

这段报错里,关键信息有四个:

字段 含义 我的经验
Tried to allocate 这次尝试分配多大显存 2.00 GiB,说明这次操作比较重
already allocated 已经占用了多少 6.32 GiB,已经用了大部分了
free 剩余多少 1.12 GiB,不够分配 2 GiB
reserved in total PyTorch 总共预留了多少 4.78 GiB,注意这个值可能比实际用的多

一个小技巧:看到「reserved in total」比「already allocated」大很多时,说明 PyTorch 的缓存机制占了不少显存。这时候可以试试 torch.cuda.empty_cache() 释放缓存。

还有一种常见的报错变体:

CUDA error: out of memory
CUDA kernel errors might be asynchronously reported

这种报错更「粗暴」,没有详细数字。我曾经在调试一个 GAN 模型时遇到过,排查了半天才发现是生成器里有个卷积层的通道数设错了,导致中间特征图爆炸。

注意:CUDA out of memory 不一定发生在模型加载时,也可能发生在训练中途。比如某个 batch 的数据特别大,或者某个层的激活值突然暴增。所以别只看初始化阶段。

显存溢出的本质

我用一张图来总结显存溢出的核心逻辑。这张 SVG 图展示了从「模型加载」到「训练报错」的完整链路。

显存溢出核心链路图 模型参数加载 权重 + 偏置 训练准备 优化器 + 梯度 + 数据 前向传播 中间激活值暴增 OOM 显存占用明细(常见分布) 模型参数 ~20% 梯度 ~15% 激活值 ~40% 优化器状态 ~25%

从这张图你能看到,显存溢出往往发生在前向传播阶段。因为中间激活值占了显存的大头(约 40%),而且随着 batch size 增大,激活值线性增长。

一句话总结:显存溢出不是玄学,是数学。搞清楚每部分占了多少,你就能精准定位问题。

避坑指南

我曾经在训练一个 7B 参数的 LLM 时,连续爆了三次显存。第一次是因为忘了开梯度检查点(gradient checkpointing),第二次是因为 batch size 设了 32 没降下来,第三次最离谱——有个数据加载器把整张 4K 图片 resize 成了原始尺寸,直接撑爆了显存。

所以我的建议是:

  • 先算后跑:用 torch.cuda.memory_summary() 看看每块显存的使用情况
  • 从小开始:batch size 从 1 开始试,逐步增加,找到临界点
  • 别信默认值:很多框架的默认 batch size 都是 64 或 128,对于大模型来说太高了
  • 监控显存碎片:有时候显存总量够,但碎片太多导致分配失败。可以用 nvidia-smi 看显存使用率

一个小工具:我习惯在训练脚本开头加一行 torch.cuda.set_per_process_memory_fraction(0.9),限制 PyTorch 最多用 90% 的显存,留点余量给系统和其他进程。

嗯,这一章先讲到这里。显存溢出其实没那么可怕,关键是你得知道它为什么发生。下一章我们会深入讲如何用工具定位具体是哪一层、哪个操作吃掉了显存。

可可精品资料库