接触过 AI 部署的人大概都遇到过这个报错:CUDA out of memory。明明买的是大显存的卡,模型也不大,为什么还是装不下?很多人的第一反应是"再加一块卡",但如果搞不清显存到底被什么吃掉了,加卡也可能只是把问题往后拖,或者干脆浪费钱。
要回答"为什么需要大显存",必须先弄清显存的三类主要消耗:模型权重、KV Cache(上下文缓存)和运行时激活值。这三者分别和参数量、上下文长度、并发数、batch size 相关,任何一项估算错误都会导致 OOM 或者卡在容量墙上跑不动。
这篇文章从显存的构成讲起,给出可操作的估算公式和经验系数,再讲清长上下文、量化、批处理对显存的影响,最后给出监测与优化显存的真实命令(含 RHEL/CentOS/Rocky 与 Debian/Ubuntu 安装方式)。文中所有字节数、倍数都是经验量级,具体以框架实际实现为准。看完你应该能自己估算"这套模型需要多大的卡"。
显存被谁吃掉了
一块 GPU 的显存,在 AI 负载下主要被这几部分占据:
- 模型权重:参数量 × 每参数字节数。FP32 是 4 字节,FP16/BF16 是 2 字节,INT8 是 1 字节,INT4 约 0.5 字节。这是最直观的一部分。
- KV Cache:自注意力机制为了不重复计算历史 token,会把每层的 Key、Value 缓存下来。它随上下文长度和并发数线性增长,长上下文场景下常常超过权重本身。
- 激活值/中间结果:前向计算中产生的临时张量。推理时随 batch 和序列长度增长,训练时因为要保存反向传播所需的中间值,体积大得多。
- 框架与 CUDA 运行时开销:CUDA context、cuDNN/cuBLAS 工作空间、通信缓冲区等。经验上每卡可能占几百 MB 到一两 GB,多个进程会让开销叠加。
- 碎片:长时间运行、反复分配释放会造成显存碎片,即使总量够也可能分配失败。
所以只按权重算显存往往会低估,实际需要预留可观余量。
参数量的显存换算
先记住几个常用换算(整数近似,便于口算):
| 精度 | 每参数字节数 | 十亿参数(1B)占用 | 百亿参数(10B)占用 |
|---|---|---|---|
| FP32 | 4 字节 | 约 4 GB | 约 40 GB |
| FP16/BF16 | 2 字节 | 约 2 GB | 约 20 GB |
| INT8 | 1 字节 | 约 1 GB | 约 10 GB |
| INT4 | 约 0.5 字节 | 约 0.5 GB | 约 5 GB |
注意这些只是权重部分。实际推理还要加上 KV Cache 和运行时开销,训练还要加梯度、优化器状态和激活值。
训练显存的经验估算:混合精度 + Adam 优化器下,参数、梯度、优化器状态(一阶、二阶动量)通常是参数量的十几倍量级(常按 16 字节每参数估),再叠加激活值。所以十亿级参数训练就可能需要数十 GB 显存,还要并行切分。激活值可以用梯度检查点(重算)换显存,代价是慢一些。
KV Cache:长上下文的隐形消耗
这是最容易被忽视的部分。KV Cache 的大小可以粗略表示为:
KV Cache ≈ 2 × 层数 × 注意力头数 × 每头维度 × 序列长度 × 每元素字节数 × 并发数
其中前面的 2 代表 Key 和 Value 两份,层数 × 头数 × 每头维度 合起来常等于隐藏维度附近的值。
关键结论:
- 上下文长度翻倍,KV Cache 翻倍;
- 并发数翻倍,KV Cache 再翻倍;
- 使用分组查询注意力(GQA/MQA)能显著减小 KV Cache。
举个例子(数值为经验示意):某模型隐藏维度数千、层数数十,单条 8K 上下文、FP16 的 KV Cache 可能只占几百 MB;但如果是 128K 上下文、并发 32,KV Cache 会膨胀到几十 GB,超过权重本身。这就是长上下文推理"吃显存"的核心原因。
因此,支持超长上下文的服务,显存瓶颈往往不在权重,而在 KV Cache。对应手段包括:用 GQA 模型、限制并发、使用 PagedAttention 这类显存分页技术、对 KV Cache 做量化。
不同负载的显存特点
| 负载类型 | 权重 | KV Cache | 激活值 | 优化重点 |
|---|---|---|---|---|
| 小模型短上下文推理 | 小 | 极小 | 小 | 提升并发 |
| 大模型短上下文推理 | 大 | 中等 | 小 | 权重精度与单卡容量 |
| 长上下文推理 | 大 | 极大 | 中等 | KV Cache 管理与分页 |
| 高并发在线服务 | 中 | 大 | 中 | 批量调度与显存分片 |
| 大模型训练 | 极大 | 中 | 极大 | 并行切分与重算 |
| 微调(LoRA) | 大 | 中 | 中 | 只训小参数,省优化器开销 |
可以看到,"需要大显存"在不同场景下原因不同:有的是权重太大,有的是上下文太长,有的是并发太高。诊断清楚才能对症下药。
监测显存使用
先看全卡概况:
nvidia-smi
关注 Memory-Usage 一行,形如 45000MiB / 81920MiB,前者是已用、后者是总量。
按时间刷新,观察显存是否随请求上涨(判断泄漏):
nvidia-smi -l 1
# 只输出关键字段,便于记录
nvidia-smi --query-gpu=timestamp,index,memory.total,memory.used,memory.free,utilization.gpu \
--format=csv -l 5
查看每个进程占用的显存:
nvidia-smi --query-compute-apps=pid,process_name,used_memory \
--format=csv
# 或看详细列表
nvidia-smi | tail -n +20
单个进程内部的显存分配情况,需要在代码里查(PyTorch 示例):
# 查看显存分配与碎片
python -c "
import torch
print(torch.cuda.memory_summary())
"
# 峰值显存
python -c "
import torch
print('reserved:', torch.cuda.max_memory_reserved()/1024**3, 'GiB')
print('allocated:', torch.cuda.max_memory_allocated()/1024**3, 'GiB')
"
清空缓存有时能缓解碎片导致的 OOM,但生产环境慎用,它会释放未使用的缓存块:
import torch
torch.cuda.empty_cache()
torch.cuda.empty_cache() 只释放 PyTorch 缓存分配器中未被使用的块,不会影响正在使用的张量,但对性能有轻微影响,不要在高频路径调用,也不要在有其他进程共享显存时随意使用。
安装监控工具。RHEL/CentOS/Rocky:
sudo dnf install -y nvtop # 需 EPEL 与较新发行版,或用源码编译
Debian/Ubuntu:
sudo apt install -y nvtop
nvtop
nvtop 提供类似 htop 的实时视图,能同时看多卡显存、利用率、功耗和温度,比反复敲 nvidia-smi 方便。
显存不足时的处理顺序
遇到 OOM,按成本从低到高依次尝试:
- 降低 batch size 或并发数:最直接,代价是吞吐下降。
- 缩短上下文长度:减少 KV Cache,代价是能处理的输入变短。
- 启用量化:INT8/INT4 让权重减半到四分之一,可能带来精度损失,需验证效果。
- 启用显存优化技术:PagedAttention、FlashAttention、KV Cache 量化、梯度检查点等。
- 调整显存分配策略:设置框架的显存占用比例,为其他进程留空间,减少碎片。
- 多卡切分:张量并行或流水线并行,把模型拆到多卡,需要高速互联。
- 换更大显存的卡或加卡:最后手段,成本最高。
一个配置示例(以某推理框架为例,参数名以实际框架为准):
# 限制每卡显存利用率,留出余量给 KV Cache 与运行时
python -m vllm.entrypoints.openai.api_server \
--model /data/models/your-model \
--gpu-memory-utilization 0.90 \
--max-model-len 32768 \
--max-num-seqs 64 \
--tensor-parallel-size 2 \
--port 8000
训练侧常用环境变量与优化:
# 梯度检查点(以 PyTorch 为例,代码内启用)
# model.gradient_checkpointing_enable()
# 混合精度
# 使用 torch.cuda.amp.autocast 与 GradScaler
# 指定可见卡
export CUDA_VISIBLE_DEVICES=0,1,2,3
常见问题
Q1:显存够装下权重,为什么还会 OOM?
多数是 KV Cache 或激活值超预期,或框架运行时开销与碎片。先看 nvidia-smi 的实际占用曲线,再算 KV Cache。
Q2:量化会不会明显掉效果?
INT8 通常影响较小,INT4 影响更明显但很多场景仍可接受。必须用业务数据做效果验证,不能只看能不能跑起来。
Q3:显存占用一直缓慢上涨怎么办?
典型显存泄漏特征。检查是否有张量被无意保留、缓存未清理、请求对象未释放。必要时给服务加定期重启或显存巡检。
Q4:多卡能不能把显存合并用?
单进程可以通过张量并行、流水线并行等方式把模型分散到多卡,但需要框架支持,且卡间通信会成为新瓶颈,不是免费的午餐。
Q5:同样的模型,为什么别人能跑我不能?
框架版本、精度、上下文长度、并发设置、算子实现都不同。逐项对齐后对比,别只比参数量。
总结
- 显存消耗主要来自模型权重、KV Cache、激活值和运行时开销四部分,只按权重估算必然低估。
- 权重按"参数量 × 精度字节数"估算;KV Cache 随上下文长度和并发数线性增长,是长上下文服务的真正瓶颈。
- 训练显存远大于推理,除了权重还要算梯度、优化器状态和激活值,可用重算等技术缓解。
- 用
nvidia-smi、nvidia-smi -l、nvtop和框架自带的显存统计来定位是权重、缓存还是泄漏问题。 - 显存不足时按"降 batch → 缩上下文 → 量化 → 优化技术 → 多卡切分 → 换卡"的顺序处理,成本从低到高。
企业QQ咨询




