开源权重的大潮一波接一波,几百 B 甚至上 T 的模型说开放就开放,很多人兴冲冲把权重拉到本地,结果卡在同一个地方:跑不起来。问题不在热情也不在网速,而在一道没算过的账——显存账。权重文件只是账本的第一页,真正的开销还包括 KV Cache、激活值和运行时本身。这道账算不清楚,买卡、选量化、定上下文长度全都是猜。
这篇 SOP 把账摊开给你看:先讲清楚显存里到底装了哪三样东西、各占多少;然后给你一个能直接套的公式和一张 Qwen3-32B 的对照表;再讲三条最常见的误判,以及怎么按显卡选精度、按场景选工具链;最后是一份从读 config.json 到压测上线的五步清单。读完你就能在下权重之前回答一个问题:这张卡到底能不能跑、能跑多大、能带多少并发。
先立一个贯穿全文的判断标准:本地部署方案没有"最好",只有"算得过来"。同样一张卡,换一个精度、换一个上下文长度、换一个并发目标,结论会完全不同。所有选型动作之前都应该是这道显存账,所有选型动作之后都应该有一次压测验证,中间凭感觉做的决定,最后都会在 OOM 报错或账单里还回来。
先算三笔账:权重、KV 缓存、运行开销
显存里的东西可以拆成三笔账,缺一笔都会翻车。
第一笔是权重。权重大小等于参数量乘以每参数字节数:BF16 和 FP16 每参数 2 字节,FP8 是 1 字节,INT4 名义上约 0.5 字节,但分组量化带着缩放因子,实际略高,通常按 0.5 到 0.6 字节估。32B 的模型 BF16 下就是 32 乘 2 除以 1024 的三次方,约 66GB——这也是为什么单张消费级卡跟 BF16 的 32B 基本无缘。
第二笔是 KV Cache,这是被算漏最多的一笔。部署工程师在技术社区分享过一个经验公式:每 token 的 KV Cache 等于 2 乘层数乘 KV 头数乘 head_dim 乘每值字节数,前面的 2 对应 K 和 V 两份。关键特性有两条:它随上下文长度和并发数线性增长,而且与权重量化无关。也就是说你把权重压到 4bit,长上下文多用户场景下,缓存照样按 FP16 的速度膨胀,占的显存可能比权重还多。Qwen3-32B 的 KV Cache 在 FP16 下约每 token 256KiB,一条 32K 上下文的单请求就要约 8.6GB,10 个并发就是约 86GB——比 BF16 权重本身还大。把缓存换成 FP8 可以直接减半,单请求 4.3GB,10 并发约 43GB。
第三笔是运行开销。CUDA context、激活值、显存碎片,这些不随模型名声变化,保守预留 4 到 12GB。算完三笔之后再整体乘 1.1 到 1.3 的余量系数,经验法则是把"权重加 KV 加激活"控制在可用显存的七八成以内,剩下的留给峰值和碎片。
把三笔账叠在一起看,你就明白为什么"模型多大"是个没有意义的问题,正确的问题永远是"模型多大、窗口多长、几个并发、什么精度"。同样的 32B 模型,32K 窗口单请求是一台机器,128K 窗口 8 并发是完全不同的另一台机器,差出来的部分全在 KV Cache 和并发预留里。
一个能直接套的公式与一张对照表
下面这段 python 伪代码把三笔账写在一起,拿到模型的 config.json 后直接套:
# 从 config.json 读取: num_hidden_layers, num_key_value_heads, head_dim
# 以及总参数量 params_b(单位:十亿)
BYTES_PER_PARAM = {"bf16": 2.0, "fp8": 1.0, "int4": 0.55}
def plan_vram(params_b, layers, kv_heads, head_dim,
precision="bf16", kv_dtype=2.0,
ctx_len=32768, concurrency=1):
# 第一笔:权重(GB)
weights = params_b * BYTES_PER_PARAM[precision] / 1024**3
# 第二笔:KV Cache(GB),每 token = 2 x 层数 x KV头数 x head_dim x 字节
kv_per_token = 2 * layers * kv_heads * head_dim * kv_dtype
kv_total = kv_per_token * ctx_len * concurrency / 1024**3
# 第三笔:运行开销,保守取中间值 8GB
overhead = 8.0
# 余量:整体乘 1.2
return (weights + kv_total + overhead) * 1.2
# Qwen3-32B, BF16 权重, FP16 缓存, 32K 单请求
print(plan_vram(32.8, 64, 8, 128)) # 权重约66GB + KV约8.6GB + 开销, 需100GB级
print(plan_vram(32.8, 64, 8, 128, precision="fp8", kv_dtype=1.0)) # 显著下降这张表用 Qwen3-32B(约 32.8B 参数,Apache 2.0 许可)做锚点,多源实测和估算口径如下:
| 精度 | 权重占用 |
|---|---|
| BF16 | 约 66GB |
| FP8 | 约 33GB |
| GGUF Q8_0 | 约 35GB |
| Q4_K_M | 约 20GB |
| NVFP4 | 约 18GB |
| AWQ/GPTQ | 约 17GB |
表里有个反直觉的地方:GGUF Q8_0 约 35GB 比 FP8 的 33GB 还略大,因为 GGUF 的逐层缩放结构带了少量额外存储。选型时别只看数字大小,还要看你的推理框架吃哪种格式。
用这道账再看"开源了不等于你能跑"就很直观。Kimi K3.1 Pro 参数量约 2.8T,BF16 下权重约 5.6TB,FP8 约 2.8TB,就算压到 INT4 也要约 1.4TB——单机家用不存在部署路径,无论你怎么量化、怎么卸载。权重开放解决的是获取问题,算力门槛还得靠这道显存账自己掂量。企业部署规划里还有一组常被引用的数字:70B 级模型开 32K 上下文,单请求的 KV Cache 就约 10GB,这还没算权重和开销。
所以下权重之前先把 config.json 打开。层数、KV 头数、head_dim、参数量全在里面,五个数字套两个公式,十分钟就能判断一张卡够不够,比下载 60GB 之后失败要便宜得多。不同模型的 KV 结构差异很大:用了分组查询注意力(GQA)的模型 KV 头数远小于注意力头数,缓存压力小很多;没用的老结构模型,同样的上下文长度缓存可能翻好几倍,这也解释了为什么同参数量的模型显存需求并不一样。
三条最常见的误判(能加载不等于能用)
第一条:只算权重不算 KV Cache。这是新手最普遍的错,也是代价最高的错。前面算过,32B 模型 32K 上下文 10 并发的缓存约 86GB,而 BF16 权重才 66GB——缓存超过权重的一半甚至反超,在长上下文场景里是常态。只按权重买卡,服务一上并发就 OOM,而且往往是压测时才暴露。
第二条:把"能加载"当"能用"。vLLM 启动成功只证明权重塞得下,真话在启动日志里:GPU KV cache size 会直接打印实际分到的缓存大小,由此推算的最大并发数才是这台机器的真实容量。日志里缓存只分到几百 MiB、并发个位数,这种"启动成功"没有生产价值。判断标准永远是压测后的实测值,不是进程没崩。
第三条:忽视存储与网络瓶颈。140GB 的权重走 1GbE 网络拉载,光传输就要约 22 分钟,冷启动体验极差;多卡部署时张量并行的 all-reduce 才是东西向流量的真正大头,PCIe 带宽和 NVLink 拓扑不规划好,卡越多不一定越快。本地部署的完整含义还包括数据面:物理断网或内网隔离、权重一次拉齐后离线运行、API 加鉴权、调用日志留痕,这些都要在规划期一起算。
精度怎么选:从 BF16 到 4bit 的阶梯
精度阶梯不是越低越好,而是按显卡挑位置。
24GB 卡(4090 这类):跑 8B 级模型用 BF16 或 FP8,配合 FP8 缓存,体验最完整;想跑 14B 到 32B 就只能上 4bit 量化(NVFP4、AWQ、GPTQ),而且上下文长度受限,32B 量化后权重约 17 到 20GB,缓存所剩无几,适合个人把玩不适合并发服务。
96GB 卡(H20、A100 x4 这类量级):跑 70B 稠密模型上 FP8,质量接近 BF16,缓存还有富余;跑大 MoE 模型用 NVFP4 或 MXFP4 更划算。
架构也是硬约束:Blackwell(算力 12.0)原生支持 FP8 和 FP4,精度阶梯能走满;Ampere(算力 8.0/8.6)只能做权重量化,没有 FP4 可言。老卡上强行套新精度,轻则报错重则性能塌方,选精度前先查自己卡的计算能力。
原则一句话:卡不够别硬上 BF16,优先官方 FP8,再不够上 AWQ/GPTQ/GGUF Q4,每降一档都用你自己的业务数据验一遍质量再定。
另外注意精度和缓存可以分开决策:权重用 4bit、缓存用 FP8 是完全合法的组合,很多生产配置就是这么搭的。反过来,权重 BF16 但缓存压到 q4_0 的组合也成立。两笔账独立结算,不要因为"权重已经是量化版了"就默认缓存也压到位了,vLLM 和 Ollama 的缓存参数都要显式传。
工具链选型:服务化与个人机两条路
服务化路线选 vLLM 或 SGLang,两者都提供 OpenAI 兼容接口。vLLM 用 --kv-cache-dtype fp8 把缓存压成 1 字节每值,省一半缓存显存;注意无校准时 scale 全部按 1.0 处理,生产建议先用 llm-compressor 做校准。SGLang 同样是主力选择,吞吐特性各有侧重,按自己压测结果定。服务化路线的共同前提是显存规划已经算清:框架只在启动时按 --max-model-len 和可用显存切缓存,切少了运行中不会自动扩。
个人机和工作站路线选 Ollama 或 llama.cpp 加 GGUF 格式,好处是格式生态最全、支持 GPU 与内存分层卸载。Ollama 设 OLLAMA_KV_CACHE_TYPE=q8_0 可以把缓存减半,q4_0 能压到约四分之一,但前提是开启 Flash Attention,否则质量损失明显。
硬件更拮据还有两条路:KTransformers 走 CPU 内存加 GPU 显存的混合卸载,把更大的模型塞进有限硬件;Strata 0.2.10 主打小显存长上下文,按实时显存余量动态收缩 KV 缓存窗口,必要时把缓存摊到内存甚至硬盘,发布说明称 8GB 卡能以 128K 上下文启动 Qwen3.8 IQ3_S;其默认推测解码 DFlash2 把显存占用从 MTP 方案的约 5.2GB 压到约 625MiB,8GB 卡能跑出每秒 63 到 73 token 的生成速度。这类极限方案的代价是吞吐和延迟波动,适合单用户体验,别直接当生产方案。
五步落地清单(含命令)
第一步,读 config.json 先算再下。拿到层数、KV 头数、head_dim 和参数量,套前面的公式把三笔账算完,再决定下不下权重,别凭感觉。
第二步,定上下文与并发。按业务里最长的输入输出定窗口,生产环境九成业务用不到 128K,32K 往往是合理起步默认;并发数按真实峰值估,别拿理想值凑。
第三步,选精度。按上一节的阶梯对照显卡和模型规模选,优先官方 FP8,其次 AWQ/GPTQ/GGUF Q4。
第四步,起服务后压测看日志。用下面的关键参数启动:
# vLLM: 服务化部署, FP8 缓存减半, 限制最大并发缓存占用
vllm serve Qwen/Qwen3-32B-FP8 \
--kv-cache-dtype fp8 \
--max-model-len 32768 \
--gpu-memory-utilization 0.9
# Ollama: 个人机 GGUF 部署, q8_0 缓存减半 (需 Flash Attention)
OLLAMA_KV_CACHE_TYPE=q8_0 \
OLLAMA_FLASH_ATTENTION=1 \
ollama serve启动后盯日志里的 GPU KV cache size 实测值,按它推算最大并发,再用真实流量压测,而不是只看"能启动"。
第五步,固定版本、锁住运维面。固定模型和框架版本、校验权重哈希,监控用 nvidia-smi 或 Prometheus 盯显存曲线,升级前灰度一周,用固定回归集对比输出再切换。
这套清单看着琐碎,但每一条都对应一次真实的翻车:不算账就下载是第一翻车,不压测就上线是第二翻车,不固定版本被一次升级打挂是第三翻车。五个步骤执行完,你会得到三个数字——权重实际占用、缓存实测大小、单卡真实并发容量,把这三个数字记进部署文档,后续任何选型讨论都有据可依。
常见问题
Q1:我的 24GB 显卡到底能跑多大的模型? A:跑 8B 级最舒服,BF16 或 FP8 权重加 FP8 缓存,32K 上下文单请求没有压力。想跑 14B 到 32B 就只能上 4bit(NVFP4/AWQ/GPTQ),32B 量化后权重约 17 到 20GB,24GB 卡装下后缓存所剩无几,只适合单请求短上下文,别指望并发服务。
Q2:量化后模型质量掉多少? A:FP8 基本无损,96GB 卡上跑 70B 稠密模型的质量接近 BF16。INT4 类(AWQ/GPTQ/Q4_K_M)在通用任务上损失通常可接受,但长尾知识和代码细节会变糊,且分组量化的缩放因子会让实际体积比 0.5 字节每参数略高。结论只能用自己的业务数据回归测试得出,别信任何"无损"宣传。
Q3:KV Cache 为什么比权重还占显存? A:因为缓存和权重量化无关。你把权重压到 4bit,缓存仍按每值 2 字节(FP16)甚至更大计价,且随上下文长度和并发线性增长。Qwen3-32B 的缓存 FP16 下每 token 约 256KiB,32K 上下文 10 并发约 86GB,超过 BF16 权重本身。所以长上下文多用户场景,缓存才是显存大头。
Q4:Ollama 和 vLLM 该选哪个? A:看场景。个人机、单用户、想快速把玩,选 Ollama 或 llama.cpp 加 GGUF,配 OLLAMA_KV_CACHE_TYPE=q8_0 省缓存;要上生产、有并发、需要 OpenAI 兼容接口接业务,选 vLLM 或 SGLang,配 --kv-cache-dtype fp8 并用 llm-compressor 校准。两者也可以先用 Ollama 验证模型效果,再迁到 vLLM 上服务化。
Q5:128K 长上下文值得开吗? A:多数生产场景不值得。开 128K 意味着缓存按 4 倍于 32K 预留,Qwen3-32B 单请求缓存就要约 34GB(FP16),大概率挤掉并发能力。生产环境九成业务用不到 128K,先分析自己业务的最长真实输入输出,再决定窗口;真有长文档需求,优先考虑检索切片而不是无脑拉满窗口。