显存博弈论:大模型推理内存消耗深度拆解
1. 概述
大语言模型(LLM)推理时显存占用分为四个主要部分:
| 组件 | 占比 | 是否与序列长度相关 | 是否与 batch size 相关 |
|---|---|---|---|
| 模型参数 | ~30-50% | 否 | 否 |
| KV Cache | ~30-60% | 是 | 是 |
| 激活值 (Activations) | ~5-15% | 是 | 是 |
| 其他(中间缓冲区等) | ~5-10% | 部分相关 | 部分相关 |
2. 模型参数显存
2.1 参数存储格式
模型参数占用与参数数量和数据类型直接相关:
显存 = 参数数量 × 每个参数占用的字节数
常用数据类型的占用:
| 数据类型 | 位宽 | 字节数 | 典型场景 |
|---|---|---|---|
| FP32 | 32-bit | 4 bytes | 训练、精度基准 |
| FP16/BF16 | 16-bit | 2 bytes | 常见推理精度 |
| INT8 | 8-bit | 1 byte | 量化推理 |
| INT4 | 4-bit | 0.5 bytes | 极致量化推理 |
示例: LLaMA-70B 模型
- FP16: 70 × 10⁹ × 2 = 140 GB
- INT8: 70 × 10⁹ × 1 = 70 GB
- INT4: 70 × 10⁹ × 0.5 = 35 GB
2.2 模型架构参数分解
以标准 Decoder-only Transformer 为例,N 层、注意力头数 H、隐藏维度 D、中间层维度 4D:
| 组件 | 参数数量 | 说明 |
|---|---|---|
| QKV 投影(合并) | N × D × 3D × 2 组(权重+偏置) | 注意力机制 |
| Attention 输出投影 | N × D × D | 注意力输出变换 |
| FFN gate + up 投影 | N × D × 4D × 2 | SwiGLU 等门控 FFN |
| FFN down 投影 | N × 4D × D | 降维投影 |
| Embedding | vocab_size × D | Token 嵌入表 |
| LayerNorm | N × D × 2 组 | RMSNorm 参数 |
| LM Head | D × vocab_size(可与 Embedding 绑定) | 最终预测层 |
2.3 多 GPU 分片
当模型参数无法单卡容纳时,使用张量并行(Tensor Parallelism, TP)或流水线并行(Pipeline Parallelism, PP):
单卡参数显存 = 总参数显存 / TP_size
以 70B-FP16 在 8×GPU 上:140 GB / 8 = 17.5 GB/卡
3. KV Cache
3.1 核心原理
在自回归解码中,每生成一个 token,注意力计算需要关注所有之前的 token。KV Cache 缓存之前所有层的 Key 和 Value 矩阵,避免重复计算。
对于单个请求、单个层、单个注意力头:
每层 KV Cache 大小 = 2 × 序列长度 × 头维度
其中因子 2 来自 Key 和 Value 两份缓存。
3.2 完整公式
单请求 KV Cache = 2 × N_layers × n_kv_heads × head_dim × seq_len × dtype_bytes
= 2 × N_layers × (D / n_heads) × n_kv_heads × seq_len × dtype_bytes
= 2 × N_layers × D × seq_len × dtype_bytes(总头维度 = D)
注意: GQA(Grouped Query Attention)场景下,n_kv_heads < n_heads,KV Cache 会成比例减少。
3.3 MHA、GQA、MQA 对比
| 类型 | Key-Value 头数 | KV Cache 相对大小 | 典型模型 |
|---|---|---|---|
| MHA | = Query 头数 | 100% | LLaMA-1 |
| GQA | < Query 头数 | 1/2 ~ 1/8 | LLaMA-2-70B, LLaMA-3 |
| MQA | 1 | 1/H | PaLM, Falcon |
3.4 实际计算示例
LLaMA-3-70B:N=80, D=8192, seq_len=4096, FP16
单请求 KV Cache = 2 × 80 × 8192 × 4096 × 2 bytes
= 10,737,418,240 bytes
≈ 10 GB
再乘以 batch size B(常见 4-64):
B=16: 160 GB(需多卡分摊)
B=64: 640 GB
结论: KV Cache 在长序列、大 batch 场景下是显存瓶颈。
3.5 多轮对话的 KV Cache
对话场景下,KVCache 随对话轮次持续增长。假设每轮输出 M 个 token:
第 t 轮后 KV Cache 大小 ≈ 2 × N × D × (prompt_len + t × M) × dtype_bytes
典型优化:
- Prefix Caching:命中相同前缀时复用 KV Cache
- 连续批处理(Continuous Batching):不同请求的 KV Cache 动态管理
4. 激活值显存
4.1 激活值的产生
前向传播过程中,中间层的输入和输出结果占据额外显存,包括:
- Attention 中间结果:Q、K、V 矩阵、Attention Score(softmax前/后)、Context 矩阵
- FFN 中间结果:gate、up 投影结果、非线性激活输出、down 投影输入
- LayerNorm 输入/输出
- Dropout Mask(推理通常不使用)
4.2 激活值大小估算
以单层计算为例:
| 中间变量 | 形状 | 占用 (FP16) |
|---|---|---|
| Q | B × S × D | 2BSD |
| K | B × S × D | 2BSD |
| V | B × S × D | 2BSD |
| Score(可选,FlashAttention 下不存在) | B × H × S × S | 2BHS² |
| Softmax 输出 | B × H × S × S | 2BHS² |
| Context | B × S × D | 2BSD |
| FFN gate | B × S × 4D | 8BSD |
| FFN up | B × S × 4D | 8BSD |
| FFN down 输入 | B × S × 4D | 8BSD |
核心观察: 使用 FlashAttention 可以消除 BHS² 级别的 Score 矩阵显存占用,大幅降低激活值。
4.3 精简估算
单层激活 ≈ (8 ~ 12) × B × S × D
总激活 ≈ N_layers × (8 ~ 12) × B × S × D
示例: LLaMA-3-70B, B=1, S=4096
总激活 ≈ 80 × 10 × 1 × 4096 × 8192 × 2 bytes
≈ 53.7 GB
示例: B=64, S=4096
总激活 ≈ 80 × 10 × 64 × 4096 × 8192 × 2 bytes
≈ 3.44 TB(无法单卡承载)
注意: 推理时很多框架会逐层释放激活值,峰值显存远低于上述总和。
5. 峰值显存综合分析
5.1 Prefill 阶段 vs Decode 阶段
| 阶段 | 参数显存 | KV Cache 显存 | 激活显存 | 瓶颈 |
|---|---|---|---|---|
| Prefill | 固定 | 低(逐步构建) | 极高 | 激活值 > 算力 |
| Decode | 固定 | 极高(持续增长) | 很低(逐 token) | KV Cache > 显存带宽 |
典型峰值分配:
- Prefill 阶段:激活值可能超过 KV Cache + 参数
- Decode 阶段:KV Cache 支配显存
5.2 完整显存公式
总显存 ≈ 参数显存 + KV Cache 显存 + 激活值显存 + 预留缓冲区
推理框架实际使用的简化模型(vLLM 等):
总显存 = 参数显存 + KV Cache 显存 + 预留(~10-20%)
其中 KV Cache 使用预分配机制,在服务启动时即固定最大的 KV Cache 池大小。
5.3 实际案例分析
以 LLaMA-3-70B (FP16) 在 8×A100-80GB 上推理:
| 组件 | 计算 | 总计 |
|---|---|---|
| 参数 (FP16, TP=8) | 140 GB / 8 | 17.5 GB/卡 |
| KV Cache (B=16, S=4096) | 10 GB × 16 / 8 | 20 GB/卡 |
| 激活值 (估算峰值) | ~2 GB | 2 GB/卡 |
| 预留 | 10% | ~4 GB |
| 合计 | ~43.5 GB/卡 |
仍有充裕空间,可以进一步提高 batch size 或序列长度。
6. Batch Size 与并发用户数对显存的影响
6.1 Batch Size 对显存各组件的影响
Batch size 对不同显存组件的影响呈非线性:
| 组件 | 与 B 的关系 | 增长率 | 说明 |
|---|---|---|---|
| 模型参数 | 无关 | 0 | 所有 batch 共享同一份参数 |
| KV Cache | 线性增长 O(B) | 1× | 每个请求独立缓存 KV,互不干扰 |
| 激活值(标准 Attention) | 线性 O(B) + 二次 O(B·S²) | 1× ~ S× | Score 矩阵使 B 和 S 的影响叠加 |
| 激活值(FlashAttention) | 线性 O(B) | ~1× | 消除了 B·S² 项,B 仅影响线性项 |
KV Cache 随 B 增长:
总 KV Cache = 单请求 KV Cache × B
激活值随 B 增长(FlashAttention 场景):
总激活 ≈ N × (5 ~ 8) × B × S × D
───────── ─── ─ ─ ─
层数 系数 B S D
6.2 Batch Size 与序列长度的交互效应
Batch size 和序列长度并非独立——它们的乘积 B×S 决定了对显存的实际压力。
显存与 B×S 的关系:
| 组件 | 与 B×S 的关系 | 实际限制因素 |
|---|---|---|
| KV Cache | O(B×S) | 受 max_num_seqs × max_model_len 上限约束 |
| 激活值 (前置层) | O(B×S) | LayerNorm、Embedding 等 |
| 激活值 (Attention Score,无 FA) | O(B×S²) | 长序列下极快膨胀 |
| 激活值 (标准 FA) | O(B×S) | 线性增长 |
关键比率: 对于固定显存预算,B 和 S 存在 trade-off:
B × S ≈ 常数(给定 KV Cache 预算下)
这意味着——增大 batch size 就必须缩短序列长度,反之亦然。
6.3 并发用户数与显存的关系
并发用户数(Concurrent Users)并不直接等于 batch size,中间经过请求调度器。
6.3.1 核心公式
running_batch = min(pending_requests, max_num_seqs, 显存余量决定的物理上限)
其中:
pending_requests:当前排队的请求数(受并发用户数影响)max_num_seqs:推理框架配置的最大同时处理数显存余量决定的物理上限:KV Cache 池剩余 slot 数
6.3.2 静态 Batching(传统方案)
内存占用 = max_batch_size × 单请求 KV Cache
所有请求集中等待,凑齐一个 batch 后一起处理:
| 并发用户数 | batch size | KV Cache 显存 | 平均排队时延 |
|---|---|---|---|
| 1 | 1 | 单请求 | 0 |
| 16 | 16 | 16× | 可变 |
| 64 | 32 (拆批) | 32× | 高 |
| N >> M | M(cap) | M× | 极高 |
问题: 静态 batching 必须等待所有请求到达或填满 batch 才开始推理,导致:
- 请求到达率波动时显存利用不均
- 空闲时 GPU 利用率低
- 请求必须对齐处理(所有请求同时结束才算完)
6.3.3 Continuous Batching(vLLM 等现代方案)
Continuous Batching 在 token 级别进行动态调度,每个请求独立推进解码步。
内存视图(某时刻 t):
Continuous Batching 的核心优势:
| 特性 | 静态 Batching | Continuous Batching |
|---|---|---|
| 内存分配时机 | 请求到达时集中分配 | token 粒度动态分配 |
| 请求退出时机 | 全 batch 完成 | 逐请求独立退出 |
| 新请求加入时机 | 下一个 batch | 任意 decode 步 |
| 显存碎片 | 高 | 低(PagedAttention) |
| 有效吞吐(同延迟约束) | 1× | 1.5~3× |
显存效率量化:
对于 M 个并发用户,平均序列长度 S_avg,Continuous Batching 的实际 KV Cache 需求:
峰值 KV Cache ≈ peak_concurrency × S_max × 单 token KV Cache
而静态 batching 的需求:
峰值 KV Cache ≈ batch_size × S_max × 单 token KV Cache
当 peak_concurrency > batch_size 时,Continuous Batching 通过动态调度将等待队列中的请求在显存中<无占用状态>,大幅降低峰值需求。
6.3.4 并发用户数 vs 显存占用曲线
显存占用
│
│ ① 参数(固定)────
│ │
│ ② KV Cache 区 ───┤
│ │ ③ 预留水位
│ │ │
│ │ ══╪══ max_num_seqs 上限
│ │ │
│ │ ┌──┴──┐
│ │ │运行中│← continuous batching
│ │ └──┬──┘
│ │ ┌──┴──┐
│ │ │排队中│← 不占显存
│ │ └─────┘
└──────────────────────────────→ 并发用户数
排队中的请求不占用 GPU 显存——只在达到
max_num_seqs上限后开始排队。这是 Concurrent Batching 的关键特性。
6.4 Service Level Objectives (SLO) 与显存规划
实际部署中,显存配置必须满足服务质量目标。核心指标:
| 指标 | 定义 | 受 B/并发影响 |
|---|---|---|
| TTFT (Time to First Token) | 首 token 延迟 | 与 prefill batch size 正相关 |
| TPOT (Time Per Output Token) | 每 token 间隔 | 与 decode batch size 正相关 |
| ITL (Inter-Token Latency) | token 间延迟 | 同 TPOT |
| 吞吐量 | tokens/s | 与 batch size 正相关 |
B 与延迟的关系(近似模型):
TTFT ∝ S_prefill × (B_prefill / GPU_compute)
TPOT ∝ (B_decode × D × N) / GPU_memory_bandwidth
B 与吞吐的关系:
Throughput (tokens/s) ≈ B_decode × (1 / TPOT)
∝ B_decode × memory_bandwidth / (B_decode × D × N)
≈ memory_bandwidth / (D × N)
当 B 足够大时,吞吐趋向于受内存带宽限制的饱和值;B 过小时,吞吐受计算延迟限制。
SLO 指导下的 max_num_seqs 选择:
给定 TPOT SLO = 50ms,TPOT = B × C (C 为每请求 token 延迟系数)
max_B = 50ms / C(满足延迟 SLO 的最大 batch)
max_num_seqs ≤ max_B(同时需满足显存容量上限)
6.5 Batch Size 的优化选择:吞吐 vs 延迟
不同 Batch Size 下的行为区间:
| 区间 | Batch Size | 显存压力 | 延迟特征 | 吞吐特征 | 适用场景 |
|---|---|---|---|---|---|
| 延迟优化 | 1~4 | 低 | 低延迟 | 低吞吐 | 实时对话、流式应用 |
| 均衡 | 4~32 | 中 | 可接受 | 较高 | 通用在线服务 |
| 吞吐优化 | 32~128 | 高 | 高延迟 | 最高吞吐 | 离线批处理、数据标注 |
| 过载 | >128 | 极高(OOM 风险) | 不可接受 | 下降(显存压力导致) | — |
典型场景下的推荐值:
| 场景 | 模型 | 推荐 max_num_seqs | 内存策略 |
|---|---|---|---|
| 实时聊天 | 8B-INT4 | 4~8 | 低延迟优先,预留充足空闲显存 |
| 代码补全 | 7B-FP16 | 16~32 | 平衡延迟和吞吐 |
| 文档分析 | 70B-FP16 | 8~16 | KV Cache 大,需限制并发 |
| 离线批量推理 | 任意 | 64~128 | 极限吞吐,可接受高延迟 |
| API 聚合服务 | 70B-INT4 | 32~64 | 适配多用户突发流量 |
6.6 并发用户数规划实战案例
场景: 使用 8×A100-80GB 部署 LLaMA-3-70B (FP16),目标服务 1000 并发用户
步骤 1:确定单卡可用 KV Cache 显存
总显存 = 80 GB
参数显存 = 17.5 GB
预留 = 8 GB (10%)
可用 KV Cache = 80 - 17.5 - 8 = 54.5 GB / 卡
总可用 KV Cache = 54.5 × 8 = 436 GB
步骤 2:计算单请求 KV Cache
单请求 KV Cache = 2 × 80 × 8192 × 4096 × 2 = 10 GB
步骤 3:估算最大并发数
max_concurrent = 436 / 10 = 43.6 ≈ 43 请求(S=4096 场景)
步骤 4:验算 SLO
TPOT ≈ (43 × 80 × 8192 × 2) / (2 TB/s × 8 GPU)
= 56.3 ms / token(满足一般交互式 SLO < 100ms)
步骤 5:1000 并发用户时
每秒到达率 = 1000 用户 × (1 / 平均思考时间) 请求/秒
假设平均思考时间 = 10s,到达率 = 100 请求/秒
平均排队长度 = 100 请求/秒 × (43 / 100) ≈ 43 请求排队
平均排队时延 ≈ 43 / 100 ≈ 0.43 秒
1000 并发用户下,系统保持约 43 请求同时在 GPU 中处理,其余排队等待,平均排队时间 < 0.5s,可接受。
6.7 关键量化结论
| # | 结论 |
|---|---|
| 1 | KV Cache 随 B 线性增长,通常在 B > 8 时即超过参数显存,成为最大组件 |
| 2 | 并发用户 ≠ batch size:连续批处理将显存占用与并发解耦,排队不占显存 |
| 3 | B×S 乘积决定显存真实压力,两者存在显存预算下的 trade-off |
| 4 | 延迟 SLO 约束了 B 的上限,即使显存充足,也需平衡 TPOT 指标 |
| 5 | Continuous Batching + PagedAttention 是现代高并发服务的显存管理基石,将有效利用率从 60% 提升至 95% |
| 6 | 显存规划需考虑峰值:用户行为有突发性,建议 max_concurrency = 预估均值的 2~3 倍 |
7. 显存优化技术
7.1 量化
| 量化方案 | 位宽 | 参数显存缩减 | 质量影响 | 典型框架 |
|---|---|---|---|---|
| FP8 | 8-bit | 50% | 极小 | TensorRT-LLM |
| INT8 | 8-bit | 50% | 小 | LLM.int8() |
| INT4(GPTQ) | 4-bit | 75% | 较小 | AutoGPTQ |
| INT4(AWQ) | 4-bit | 75% | 较小 | AWQ |
| NF4 | 4-bit | 75% | 较小 | bitsandbytes |
| 混合精度(FP16 + INT8) | 部分8-bit | 30-40% | 很小 | vLLM |
7.2 显存管理策略
| 策略 | 机制 | 效果 |
|---|---|---|
| PagedAttention | 分页式 KV Cache 管理,类似虚拟内存 | 消除显存碎片,利用率提升至~95% |
| Prefix Caching | 自动检测并复用公共前缀 KV Cache | 多轮对话/系统提示词场景节省 30-60% |
| Continuous Batching | 请求级别动态调度,替换静态 batch | 显存利用率大幅提升 |
| Memory Sharing | Multi-LoRA 共享基座模型参数 | 多 LoRA 场景显存近乎零增长 |
| 激活值 Checkpointing (推理) | 不保存中间激活,需要时重算 | 激活值显存降至接近 0 |
| 显存 Offloading | KV Cache / 参数卸载到 CPU/NVMe | 突破 GPU 显存上限,但增加延迟 |
7.3 FlashAttention
FlashAttention 在不近似的情况下将 Attention 计算分块进行,核心收益:
- 消除 Score 矩阵(B×H×S×S)显存占用:不实例化完整的 S×S 注意力矩阵
- 减少 HBM 读写:通过 tiling 在 SRAM 中完成计算
- 不等价于近似:与标准 Attention 数学严格等价
显存收益公式(单层):
标准 Attention + 非 in-place 操作:
峰值显存 ≈ 2BSD + 3BSD + 2BHS² + 2BHS² + 2BSD = 10BSD + 4BHS²
FlashAttention:
峰值显存 ≈ 2BSD + 3BSD + 少量 tile 缓存 ≈ 5BSD + 极小
7.4 深度优化的推理策略
| 策略 | 描述 | 适用场景 |
|---|---|---|
| Chunked Prefill | 将长 prompt 拆分为多个 chunk 混合 decode | 减少 TTFT,抑制 OOM |
| Speculative Decoding | 小模型起草 + 大模型验证,减少大模型调用 | 降低 KV Cache 峰值占用(间接) |
| SplitFuse | 动态拆分 prefill 和 decode,消除静默期 | 提升 GPU 利用率,稳定显存 |
| Sparse Attention | 只保留部分 token 的注意力连接 | 超长序列场景 |
8. Batch Size 与并发用户规划速查
8.1 不同模型在不同并发下的显存估算
以下估算基于 FP16、seq_len=4096、Continuous Batching 场景,单卡 A100-80GB:
| 模型 | 参数量(FP16) | 可用 KV Cache/卡 | 单请求 KV Cache | 每卡最大并发(seq=4K) | 8卡最大并发 |
|---|---|---|---|---|---|
| LLaMA-3-8B | 16 GB | 56 GB (1卡) | 1.1 GB | ~50 | — |
| LLaMA-3-70B (TP=8) | 17.5 GB | 54.5 GB | 10 GB/8=1.25 GB | ~43 | ~43 |
| LLaMA-3-70B (INT4, TP=4) | 8.75 GB | 63.25 GB | 10 GB/4=2.5 GB | ~25 | ~100 |
| Qwen2.5-72B (TP=8) | 18.2 GB | 53.8 GB | ~1.3 GB | ~41 | ~41 |
| LLaMA-3.1-405B (FP8, TP=16) | 25.3 GB | 46.7 GB | ~0.6 GB | ~77 | ~77 |
8.2 并发用户与所需 GPU 数量速查
目标:TPOT < 100ms/token,seq_len=4096,FP16
| 并发用户数 | 模型 8B (INT4) | 模型 8B (FP16) | 模型 70B (FP16, TP=8) | 模型 405B (FP8, TP=16) |
|---|---|---|---|---|
| 10 | 1×GPU 24GB | 1×GPU 24GB | 4×GPU 80GB | 8×GPU 80GB |
| 50 | 1×GPU 80GB | 2×GPU 80GB | 4×GPU 80GB | 16×GPU 80GB |
| 100 | 2×GPU 80GB | 4×GPU 80GB | 8×GPU 80GB | 32×GPU 80GB |
| 500 | 4×GPU 80GB | 8×GPU 80GB | 32×GPU 80GB | 64×GPU 80GB |
| 1000 | 8×GPU 80GB | 16×GPU 80GB | 64×GPU 80GB | 128×GPU 80GB |
假设平均请求长度 4096 tokens,输出 1024 tokens,Continuous Batching 效率 ~90%,TPOT SLO < 100ms。
8.3 显存配置速查公式
最大并发数 ≈ 可用 KV Cache 总显存 / 单请求 KV Cache
可用 KV Cache 总显存 = (GPU 总显存 - 参数显存) × 0.9(预留 10% 开销)
单请求 KV Cache = 2 × N_layers × D × avg_seq_len × dtype_bytes
所需 GPU 数 = 参数显存 / 单卡显存(参数维度)
∩ 目标并发 × 单请求 KV Cache / 单卡可用 KV Cache(并发维度)
取两者最大值
9. 显存估算速查表
9.1 常见模型参数大小
| 模型 | 参数量 | FP16 | INT8 | INT4 |
|---|---|---|---|---|
| LLaMA-3-8B | 8.0B | 16 GB | 8 GB | 4 GB |
| LLaMA-3-70B | 70.6B | 141 GB | 70 GB | 35 GB |
| LLaMA-3.1-405B | 405B | 810 GB | 405 GB | 203 GB |
| Qwen2.5-72B | 72.7B | 145 GB | 73 GB | 36 GB |
| DeepSeek-V3 | 671B (MoE, 37B active) | 1342 GB (74B active) | — | — |
| Mistral-7B | 7.3B | 14.6 GB | 7.3 GB | 3.7 GB |
| Mixtral-8x7B | 46.7B (MoE) | 93 GB | 47 GB | 23 GB |
9.2 KV Cache 估算表
条件:N_layers × D = 80 × 8192 (LLaMA-3-70B 近似),FP16
| Batch Size | Seq Len 2048 | Seq Len 4096 | Seq Len 8192 | Seq Len 32768 |
|---|---|---|---|---|
| 1 | 5 GB | 10 GB | 20 GB | 80 GB |
| 4 | 20 GB | 40 GB | 80 GB | 320 GB |
| 16 | 80 GB | 160 GB | 320 GB | 1.28 TB |
| 64 | 320 GB | 640 GB | 1.28 TB | 5.12 TB |
9.3 多 GPU 部署推荐配置
| 模型 | 精度 | 最低 GPU 数* | 推荐 GPU 数 | 每卡显存 | 框架 |
|---|---|---|---|---|---|
| LLaMA-3-8B | FP16 | 1 | 1 | 24 GB+ | vLLM |
| LLaMA-3-8B | INT4 | 1 | 1 | 8 GB+ | llama.cpp |
| LLaMA-3-70B | FP16 | 4 | 8 | 80 GB | vLLM / SGLang |
| LLaMA-3-70B | INT4 | 1 | 2 | 80 GB | TensorRT-LLM |
| LLaMA-3.1-405B | FP8 | 8 | 16 | 80 GB | vLLM / TRT-LLM |
| DeepSeek-V3 | FP8 | 4 | 8 | 80 GB | SGLang / vLLM |
*最低 GPU 数:仅能容纳参数,实际需要 +30-50% 给 KV Cache。
10. 主流推理框架显存管理对比
| 特性 | vLLM | TensorRT-LLM | SGLang | llama.cpp |
|---|---|---|---|---|
| 内存管理 | PagedAttention | 自定义分配器 | RadixAttention | 简单预分配 |
| KV Cache 复用 | Prefix Caching | 手动实现 | 自动 Radix Tree | 无 |
| FlashAttention | ✅ | ✅ | ✅ | ✅ |
| 量化支持 | AWQ/GPTQ/FP8 | FP8/INT4/INT8 | AWQ/GPTQ/FP8 | GGUF (2-8 bit) |
| Continuous Batching | ✅ | ✅ | ✅ | ❌ |
| 显存利用率 | ~95% | ~90% | ~95% | ~85% |
11. 调优指南
11.1 显存不足时的排查步骤
显存不足(OOM)
├─ 参数过大
│ ├─ 使用更低精度(FP16 → INT8 → INT4)
│ └─ 增加 GPU 数量(增大 TP 或 PP)
├─ KV Cache 过大
│ ├─ 减小 max_num_seqs(batch size)
│ ├─ 减小 max_model_len(最大序列长度)
│ ├─ 使用 GQA/MQA 架构
│ └─ 启用 Prefix Caching
└─ 激活值过大(主要在 Prefill)
├─ 使用 FlashAttention
├─ 启用 Chunked Prefill(chunk 大小调小)
└─ 减小 Prefill 阶段的最大 batch size
11.2 常用显存监控工具
nvidia-smi # 实时 GPU 显存占用
nvitop # 更友好的显存监控
torch.cuda.memory_summary() # PyTorch 详细显存分析
nsys profile # NVIDIA Nsight 深度性能分析
vllm status # vLLM 运行状态(含 KV Cache 利用率)
12. 关键结论
- 推理显存三大部分:参数 + KV Cache + 激活值,其中 KV Cache 在长序列、大 batch 时占比最大
- Prefill vs Decode 显存特征不同:Prefill 以激活值为主,Decode 以 KV Cache 为主
- 显存优化最有效手段:模型量化(降低参数) + PagedAttention(提升利用率) + FlashAttention(消除激活值尖峰)
- MoE 架构天然优势:等效参数量下,激活参数量小,KV Cache 仅与总维度相关,参数显存仅为活跃专家部分
- 长上下文场景:KV Cache 成为绝对瓶颈,需要结合 Prefix Caching、Sparse Attention、Offloading 等技术
- 框架选择:高吞吐场景选 vLLM/SGLang,极致延迟选 TensorRT-LLM,本地部署选 llama.cpp
🔧 附录:必备工具
🚀 LLM 推理显存与性能计算器
告别手动估算,一键算出你的显存需求
在线交互式工具,输入模型参数、精度、序列长度、并发数等,自动估算显存需求和推理性能:
🔗 立即打开 → LLM 推理显存与性能计算器
更多推荐



所有评论(0)