本地部署大模型要多少显存:一套能算准的公式
一句「7B 需要 14G」为什么经常不准
网上常说「FP16 下 1B 参数约 2GB」,这是只算了模型权重。真实部署时显存被四块吃掉:
总显存 = 权重 + KV Cache + 激活值 + 框架开销
其中 KV Cache 随上下文长度和并发数线性增长,经常比权重还大。这就是为什么 14GB 的模型在 16GB 卡上仍然 OOM。
一、权重(最好算的一项)
权重显存 = 参数量 × 每参数字节数
| 精度 | 每参数字节 | 说明 |
|---|---|---|
| FP32 | 4 B | 训练用,推理基本不用 |
| FP16 / BF16 | 2 B | 推理默认 |
| FP8 / INT8 | 1 B | 质量损失很小,推荐 |
| INT4 / Q4 | ≈0.5~0.55 B | 消费级显卡的主力,Q4_K_M 约 4.5~4.8 bit/参数 |
对照表(只算权重):
| 模型规模 | FP16 | INT8 | Q4 |
|---|---|---|---|
| 7B | 14 GB | 7 GB | ≈ 4 GB |
| 13B | 26 GB | 13 GB | ≈ 7.5 GB |
| 32B | 64 GB | 32 GB | ≈ 19 GB |
| 70B | 140 GB | 70 GB | ≈ 40 GB |
MoE 结构(如 DeepSeek 的开放权重版本)要按总参数算显存,不是激活参数。总参数 600B+ 的模型,即使单次只激活几十 B,权重本身也要几百 GB。
二、KV Cache(最容易被忽略,也最容易爆)
Transformer 推理时要缓存历史 token 的 Key/Value 向量,避免重复计算。它的大小:
KV Cache = 2 × 层数 × KV维度 × 序列长度 × 并发数 × 每元素字节
其中 KV维度 = KV头数 × head_dim(用了 GQA 的话比 hidden size 小很多)。
举个具体例子:一个 8B 级别模型,32 层、hidden 4096、GQA 8 个 KV 头、head_dim 128,FP16:
KV维度 = 8 × 128 = 1024
每 token KV = 2 × 32 × 1024 × 2 B = 128 KB
8K 上下文、单条序列 = 128 KB × 8192 ≈ 1 GB
8K 上下文、并发 8 条 ≈ 8 GB ← 比权重还大
两个结论:
- 长上下文很贵。32K 上下文下,KV Cache 是 8K 时的 4 倍
- 并发也是线性的。vLLM 的 PagedAttention 能减少碎片、提高利用率,但总字节数不会凭空消失
三、激活值与框架开销(估算即可)
这部分不精确,按经验留:
- CUDA context / 框架本身:约 0.3~0.8 GB
- 前向激活(随 batch 和序列长度增长):约 0.5~2 GB
- 建议再留 10%~20% 余量给内存碎片和峰值
四、完整算一遍:24G 单卡能跑什么
假设卡是 24GB,留 2GB 给系统和框架,可用约 22GB。
场景 A:7B Q4,8K 上下文,并发 1
权重 4 GB + KV 1 GB + 激活 1 GB ≈ 6 GB ✅ 轻松
场景 B:13B Q4,8K 上下文,并发 4
权重 7.5 GB + KV(4条) 4 GB + 激活 2 GB ≈ 13.5 GB ✅ 可以
场景 C:32B Q4,8K 上下文,并发 1
权重 19 GB + KV ~1.5 GB + 激活 1 GB ≈ 21.5 GB ⚠️ 勉强,余量很小
实际部署时稍微长一点的上下文就会 OOM,通常要把上下文压到 4K 或降低量化比特数。
场景 D:70B Q4
权重 ≈ 40 GB ❌ 24G 单卡跑不了,需要 48G 卡或双卡
经验速查(24GB 单卡):
- 7B/8B FP16:能跑
- 13B/14B Q4/Q5:舒服
- 32B Q4:极限,要压上下文
- 70B:跑不了
五、不够显存时的六种做法
| 方法 | 代价 | 适用 |
|---|---|---|
| 量化到 Q4 / INT8 | 轻微质量损失 | 首选,几乎无损 |
| 缩短上下文 | 长文档能力下降 | 先做 RAG 再考虑 |
| 升 INT4 + 小 KV(GQA 模型) | 质量略降 | 选原生带 GQA 的模型 |
CPU 卸载(llama.cpp -ngl 部分层) |
速度大幅下降 | 应急 |
| 多卡张量并行 | 硬件成本 | 70B 级 |
| 换更小模型 | 能力下降 | 很多场景够用 |
量化优先级:Q5_K_M > Q4_K_M > Q3。Q4_K_M 是质量/体积的常见平衡点;再往下(Q3 及以下)在代码和数学任务上退化明显。
六、选运行时:先看场景
| 运行时 | 显存效率 | 吞吐 | 适合 |
|---|---|---|---|
| Ollama | 一般(自动量化) | 低 | 本地开发、快速验证 |
| llama.cpp | 高(GGUF 极致优化) | 中 | CPU/低显存/边缘设备 |
| vLLM | 高(PagedAttention) | 最高 | 生产服务、高并发 |
| LM Studio | 一般 | 低 | 图形化尝鲜 |
关键:Ollama / vLLM 都提供 OpenAI 兼容端点,部署完之后调用代码不用改:
# Ollama
ollama serve # 默认 127.0.0.1:11434/v1
# vLLM
vllm serve Qwen/Qwen2.5-7B-Instruct --port 8000 --max-model-len 8192
from openai import OpenAI
client = OpenAI(api_key="none", base_url="http://localhost:8000/v1")
七、上线前的检查清单
- [ ] 权重显存按实际量化精度算,不是按 FP16
- [ ] KV Cache 按「最大上下文 × 最大并发」算,不是按单条
- [ ]
max_model_len已设置(vLLM 不设会按模型默认值预留,可能直接 OOM) - [ ] 并发上限已设置(
--max-num-seqs),避免打满 - [ ] 留了 10%~20% 余量
- [ ] 压测过真实场景的输入长度分布(长尾比平均值重要)