本地部署大模型,从模型卡估算本地显存
文章目录
- 1. 简单口算的局限
- 2. 先说结论
- 3. 四项字段的作用
- 3.1 总参数(total params)
- 3.2 激活参数(activated / active params)
- 3.3 上下文长度(context)
- 3.4 量化格式(quantization)
- 4. 一套可执行的估算顺序
- 4.1 权重显存(规划公式)
- 4.2 KV 显存(规划公式)
- 4.3 运行时余量
- 5. 用脚本做粗算
- 5.1 稠密 7B,Q4,4K 上下文
- 5.2 同模型拉到 32K 上下文
- 5.3 MoE:总参 47B,激活 13B
- 6. 上机采样,对照纸面数字
- 7. 检查清单
- 8. 常见误区
- 8.1 只用总参数 × 2
- 8.2 把激活参数直接当成显存需求
- 8.3 按模型宣传的最大上下文估日常需求
- 8.4 粗算通过就下单旗舰卡
- 8.5 不同框架共用同一套“经验 GB 数”
- 9. 术语速查
- 10. 小结
- 11. 相关阅读
摘要:本地部署前,很多人只用“7B ≈ 14GB”这种口算决定买不买卡、能不能跑。纸面公式在稠密 FP16 场景偶尔够用,一遇到量化、长上下文和 MoE,偏差就会很大。本文把模型卡上的总参数、激活参数、上下文长度、量化格式放进同一套估算流程,并给出可运行的粗算脚本。适合已经会看模型卡、准备本机或工作站部署的人。数字只作规划参考,最终以目标推理框架在你机器上的实测为准。
承接前文:
- 大模型里的 MoE
- 本地部署大模型的详细考虑(含脚本/代码)
- 本地部署大模型前,要不要加显卡
建议目录:
mkdir-p~/vram-lab/{notes,scripts,logs}cd~/vram-lab# 本文:estimate_vram.py / probe_runtime_mem.sh / vram_checklist.md| 文件 | 作用 |
|---|---|
scripts/estimate_vram.py | 用模型卡字段做显存粗算 |
scripts/probe_runtime_mem.sh | 推理时采样 GPU / 系统内存 |
notes/vram_checklist.md | 估算与实测对照清单 |
1. 简单口算的局限
常见口算是:
参数量(B)× 2 ≈ FP16 权重大小(GB)
它只覆盖了一种很窄的情况:稠密模型、权重以 FP16/BF16 常驻、上下文不长、忽略框架开销。下面任一条件出现,口算就会漂:
| 变化 | 影响 |
|---|---|
| 换成 Q4 / Q5 / INT8 | 每参数字节数下降,权重显存明显变小 |
| 上下文从 2K 拉到 32K / 128K | KV 缓存可能从“可忽略”变成主角 |
| MoE 总参很大、激活参较小 | 算力直觉和权重占用不再是同一条线 |
| batch > 1 或并发会话 | KV 与临时缓冲一起放大 |
| 不同推理引擎 | 是否卸载专家、是否分页 KV,结果差一截 |
图1. 总参数、激活参数、上下文、量化,缺一项都容易估错。
2. 先说结论
| 目标 | 更该盯的字段 |
|---|---|
| 磁盘能不能放下 | 总参数 + 量化后体积 / 文件大小 |
| 单次算力与延迟直觉 | 激活参数(MoE 尤其重要) |
| 长对话会不会爆显存 | 上下文长度 + KV 精度 + batch |
| 权重常驻显存大概多少 | 常驻参数量 × 每参数字节 |
| 最终能不能上线 | 粗算 + 余量 + 同任务实测 |
再压成四条:
- 显存不是只有权重,KV 和运行时开销经常被漏掉。
- 量化先改的是每参数字节数;上下文先改的是 KV。
- MoE 的激活参数更适合理解算力;权重显存仍要看加载策略,默认常按总参保守估。
- 粗算只用于排除明显不可能的组合,下单或定案前必须实测。
图2. 规划时至少拆成:权重 + KV + 运行时余量。
3. 四项字段的作用
3.1 总参数(total params)
总参数回答的是:这个模型“装了多大一箱零件”。
- 影响下载体积、磁盘、冷启动加载时间
- 多数本机加载器会把专家权重也放进可寻址内存/显存池(除非明确卸载)
- 看模型卡时,优先同时找官方给出的量化后文件大小
3.2 激活参数(activated / active params)
激活参数回答的是:处理一个 token 时,大约有多大规模在参与计算。
- 对理解 MoE 的延迟上限很有用
- 不等于“显卡只需要装下激活参数那么大的权重”
- 详见:大模型里的 MoE
3.3 上下文长度(context)
上下文主要推高 KV 缓存:
- 近似随
seq_len × batch增长 - 长上下文模型卡写着“支持 128K”,不代表你的 12GB 卡能开满 128K
- 实务上先定业务需要的上下文,再反推显存,而不是先开到模型宣称上限
3.4 量化格式(quantization)
量化改的是“每个参数大概占多少字节”,以及一定的精度损失。
| 常见标签 | 粗算用字节/参数 | 备注 |
|---|---|---|
| FP16 / BF16 | 2.0 | 基线 |
| INT8 / Q8 | 1.0 | 视实现而定 |
| Q5 | ~0.625 | 不同打包略有出入 |
| Q4 | ~0.5 | 本机很常见 |
| Q3 | ~0.375 | 更省,质量风险更高 |
这些是规划用近似值。GGUF / GPTQ / AWQ 的真实体积以文件大小和框架文档为准。
4. 一套可执行的估算顺序
图3. 先读卡,再拆权重与 KV,最后加余量并实测。
4.1 权重显存(规划公式)
权重字节 ≈ N resident × bytes_per_param \text{权重字节} \approx N_{\text{resident}} \times \text{bytes\_per\_param}权重字节≈Nresident×bytes_per_param
其中:
- 稠密模型:N resident N_{\text{resident}}Nresident通常用总参数
- MoE:默认先用总参数做保守估计;只有确认引擎按需加载专家时,才改用激活参数
4.2 KV 显存(规划公式)
一个常用近似:
KV 字节 ≈ 2 × L × H k v × d × S × B × b k v \text{KV 字节} \approx 2 \times L \times H_{kv} \times d \times S \times B \times b_{kv}KV字节≈2×L×Hkv×d×S×B×bkv
| 符号 | 含义 |
|---|---|
| (L) | 层数 |
| (H_{kv}) | KV head 数 |
| (d) | head dim |
| (S) | 上下文长度 |
| (B) | batch / 并发序列数 |
| (b_{kv}) | 每个 KV 元素字节数(FP16 常取 2) |
模型卡若没写全 (H_{kv}) 和 (d),先用同系列公开配置,或先用“上下文翻倍、KV 近似翻倍”做相对判断。
4.3 运行时余量
框架临时缓冲、显存碎片、驱动预留,纸面上很难估准。实务做法:
- 先算 权重 + KV
- 再加 15%~25% 运行时
- 整体再留 20%~40% 安全余量
- 上机实测
图4. 激活参数帮你理解算力;权重显存要看总参和是否卸载。
5. 用脚本做粗算
保存为scripts/estimate_vram.py(仓库内已提供同名脚本)。
5.1 稠密 7B,Q4,4K 上下文
python3 scripts/estimate_vram.py\--total-b7\--quantq4\--context4096\--layers32\--kv-heads8\--head-dim128你会看到类似拆分:
weights:权重大致占用kv_cache:当前上下文下的 KVwith_margin:加余量后的规划值
5.2 同模型拉到 32K 上下文
python3 scripts/estimate_vram.py\--total-b7\--quantq4\--context32768\--layers32\--kv-heads8\--head-dim128对比两次输出里的kv_cache:上下文变长时,爆显存往往先发生在 KV,而不是权重突然变大。
5.3 MoE:总参 47B,激活 13B
默认按总参估权重(更保守,也更接近很多本地加载行为):
python3 scripts/estimate_vram.py\--total-b47\--activated-b13\--quantq4\--context8192\--layers32\--kv-heads8\--head-dim128若你明确知道引擎只常驻激活专家权重,再加上:
--moe-active-weights不要默认打开它。多数情况下,先按总参保守估,更不容易买错预期。
输出 JSON 便于记日志:
python3 scripts/estimate_vram.py --total-b7--quantq4--context8192--json\|teelogs/est_7b_q4_8k.json6. 上机采样,对照纸面数字
粗算通过后,用同一验收任务看真实占用。保存为scripts/probe_runtime_mem.sh:
#!/usr/bin/env bashset-euopipefail# 用法:# ./probe_runtime_mem.sh 15# 在另一个终端启动推理服务/对话,本脚本采样 15 秒sec="${1:-15}"ts="$(date+%Y%m%d_%H%M%S)"out="logs/mem_${ts}.txt"mkdir-plogs{echo"=== host mem ==="free-hechoifcommand-vnvidia-smi>/dev/null2>&1;thenecho"=== nvidia-smi sample ==="for((i=0;i<sec;i++));dodate'+%F %T'nvidia-smi --query-gpu=name,memory.total,memory.used,utilization.gpu--format=csvsleep1doneelseecho"nvidia-smi not found"fi}|tee"$out"echo"saved$out"用法:
chmod+x scripts/probe_runtime_mem.sh# 终端 A:启动 ollama / vLLM / 你的服务并跑固定提示词# 终端 B:./probe_runtime_mem.sh20把峰值memory.used写回清单,和with_margin对比。若实测系统性高于粗算,优先检查:上下文是否被框架自动抬高、是否多会话、是否还有草稿模型常驻。
图5. 规划值通过后,仍以同任务实测为准。
7. 检查清单
保存为notes/vram_checklist.md:
# 模型卡显存估算清单 ## 从模型卡抄下 - [ ] 总参数 - [ ] 激活参数(如有) - [ ] 目标量化格式 / 权重文件大小 - [ ] 业务需要的上下文,而不是宣传上限 - [ ] 层数、KV heads、head dim(或同系列配置) ## 粗算 - [ ] 权重显存 - [ ] KV 显存(按业务上下文 + batch) - [ ] 运行时 + 安全余量 - [ ] MoE 是否按总参保守估计权重 ## 实测 - [ ] 同一提示词 / 同一上下文 - [ ] 记录峰值显存与是否换出/失败 - [ ] 记录 tokens/s 是否可接受决策时可直接用这张表:
| 粗算结果 | 建议动作 |
|---|---|
| 余量后仍明显高于显卡容量 | 降上下文、换更重量化、换更小激活规模,或换硬件 |
| 接近上限(余量 < 15%) | 先实测;不要只看纸面“刚好放下” |
| 余量充足 | 仍做一次峰值采样,再定日常默认上下文 |
| MoE 总参很大但激活小 | 分别评估磁盘/加载与延迟,不混成一个数字 |
8. 常见误区
8.1 只用总参数 × 2
忽略量化与 KV 后,长上下文场景几乎必然误判。
8.2 把激活参数直接当成显存需求
对 MoE 尤其危险:算得少,不等于权重没加载。
8.3 按模型宣传的最大上下文估日常需求
业务若只需 4K~8K,就按业务值估;宣传上限留给压力测试。
8.4 粗算通过就下单旗舰卡
先用现有机器实测瓶颈,再决定加卡。相关判断见:本地部署大模型前,要不要加显卡。
8.5 不同框架共用同一套“经验 GB 数”
vLLM、llama.cpp、Ollama 对分页、卸载、多会话的策略不同,迁移时要重测。
9. 术语速查
| 术语 | 本文用法 |
|---|---|
| 模型卡 | 模型页/README 中的参数与限制说明 |
| 总参数 | 模型全部参数规模 |
| 激活参数 | 单次前向大致参与计算的参数规模 |
| 量化 | 降低权重数值精度以减小体积与带宽 |
| KV 缓存 | 推理时缓存的 Key/Value,随上下文增长 |
| 余量 | 给碎片、驱动和框架开销预留的安全空间 |
| 常驻权重 | 实际留在显存/内存中的权重量 |
10. 小结
从模型卡估本地显存,可靠做法是四项一起看:
- 总参数 → 体积与保守权重占用
- 激活参数 → 算力与延迟直觉(MoE)
- 上下文 / batch → KV
- 量化 → 每参数字节数
然后:粗算 → 加余量 → 同任务实测。纸面数字负责快速排除不可能;实测数字负责最终决策。
11. 相关阅读
- 大模型里的 MoE
- 本地部署大模型的详细考虑(含脚本/代码)
- 本地部署大模型前,要不要加显卡
- 本地大模型跑通了,为什么还是不好用
- 本地部署大模型:显卡/Orin
如果后面继续写相关主题,可以再展开:
同一张卡上,上下文、batch 和量化怎么联动调,才能把可用显存打满又不频繁失败
相关链接:
- Hugging Face Model Cards
- NVIDIA nvidia-smi 用户指南
- GGUF 格式说明(llama.cpp 生态常用)
如果这篇帮你把模型卡数字翻译成可执行的显存规划,欢迎点赞、收藏,也欢迎关注后续更新。
