模型量化怎么选:不看别人的跑分,用自己的验收标准决定上不上
量化的诱惑非常直接:同一张卡,本来装不下的模型现在装得下了;或者模型不变,能开的并发一下子多出一截。对于卡本来就紧张的团队,这几乎是唯一一个「不加钱就能扩容」的旋钮。
于是很多人的决策路径变成了这样——搜一圈,看到几篇文章说「INT4 几乎无损」,心里一松,直接上 INT4,上线一周后发现结构化输出偶尔崩、长链推理的答案开始飘,回头查却查不出是哪一步出的问题。
问题不在于那些文章说谎,而在于你没法验证它测的是不是你的任务。别人的「几乎无损」测的可能是短文本分类,你的场景可能是要求严格 JSON 格式的多轮工具调用。这两件事对数值误差的容忍度完全不在一个量级。「能跑」和「能用」是两件事,而把这两件事分开的唯一办法,是你自己拿业务样本测一遍。
这篇文章不给你任何量化方案的跑分和质量损失数字——给了也不可信。这里讲三件能真正复用的东西:量化到底省了哪块显存、它在什么地方会伤到你、以及一套你自己就能跑完的评测流程。
一、先算清楚:量化省的是哪一块
权重那部分,是一道纯算术题
模型权重占的显存,算法很简单:
权重显存 ≈ 参数量 × 每个参数的字节数
每个参数占几个字节,是数据类型的定义,不需要任何实测:
| 精度 | 每参数字节数 |
|---|---|
| FP32 | 4 |
| FP16 / BF16 | 2 |
| FP8 / INT8 | 1 |
| INT4 | 0.5 |
拿一个假设值演示一遍。假设某个模型有 100 亿参数(也就是 1×10¹⁰),按 1 GB = 10⁹ 字节换算:
- FP16:1×10¹⁰ × 2 = 2×10¹⁰ 字节 = 20 GB
- INT8:1×10¹⁰ × 1 = 1×10¹⁰ 字节 = 10 GB
- INT4:1×10¹⁰ × 0.5 = 5×10⁹ 字节 = 5 GB
如果按显卡规格常用的 1 GiB = 2³⁰ 字节来换算,上面三个数分别约是 18.6 GiB、9.3 GiB、4.7 GiB。两套单位差了大约 7%,卡在边缘时这 7% 足以决定装不装得下,所以自己算的时候要先把单位定死。
这里的 100 亿是我随手取的假设值,不对应任何具体模型。 你要做的是把你自己模型的参数量代进去,而不是记住这几个数。
结论是干净的:从 FP16 降到 INT4,权重部分理论上降到四分之一。这部分收益是确定的、可预测的、不需要实验的。
被大多数人忽略的另一半:KV cache 不一定跟着降
上面那句话里的「权重部分」四个字,是这一节的全部重点。
推理时显存被四样东西吃掉:模型权重、KV cache、激活值与临时缓冲、以及显存碎片和框架自身开销。量化权重只动了第一样。
KV cache 是随请求动态增长的那部分,它大致随着这几个量一起放大:并发的序列条数 × 每条序列已经积累的 token 数 × 模型层数 × 每层每 token 要缓存的 K/V 元素数 × KV 的存储精度字节数。完整的估算公式我在显存估算怎么做里写过,这里只强调一个结构性事实:
KV cache 有它自己的精度设置,和权重的量化精度是两个独立的开关。 把权重量化到 INT4,不会自动让 KV cache 也变成 INT4。具体开关叫什么、支持哪些取值,以你用的推理框架官方文档当次为准。
这一点直接决定了「量化能不能解决你的问题」,判断方法是先看你的瓶颈长什么样:
- 瓶颈是「模型根本装不进这张卡」:那是权重问题,量化直接命中,收益接近上面算出来的比例。
- 瓶颈是「模型装得下,但一开并发或一放长上下文就 OOM/排队」:那是 KV cache 问题。量化权重腾出来的空间确实会转化成更多 KV cache 空间,但它是间接收益,规模远小于你按四分之一算出来的预期。
我见过团队为了解决高并发下的排队问题去做 INT4 量化,做完发现并发只多了很有限的一点,还额外背上了质量风险——因为他们真正缺的是 KV cache 空间,而权重从一开始就装得下。在动手量化之前,先分清楚你缺的是哪块显存,这一步花十分钟,能省掉两周的白工。
二、量化会损失什么:讲机制,不给数字
低比特量化的本质是用更少的离散档位去表示原本连续分布的权重值。档位变少,每个权重被映射到最近档位时就产生了误差。这个误差单看一层很小,但它会在网络里往前传播,并且在自回归生成中,前一个 token 的偏差会作为后续 token 的输入继续放大。
所以损失在哪些任务上更容易暴露,是有规律可循的:
容易暴露的:
- 长链推理。每一步的小偏差会在推理链上累积,中间某一步选错分支,后面整条链就跑偏了。链越长,暴露概率越高。
- 精确数值处理。涉及计算、单位换算、数字抄写的场景,答案是离散的对错,没有「差不多对」。
- 代码生成。语法有硬约束,一个符号错了就是不能运行,不存在部分正确。
- 格式严格的结构化输出。要求返回合法 JSON、固定字段、可被下游程序解析时,采样时一个低概率 token 被选中就可能触发格式崩坏,下游直接抛异常。这类失败往往还是间歇性的,最难排查。
- 长上下文中的细节召回。要从很长的输入里精确提取某个具体信息时,判别力下降会更明显。
相对不敏感的:
- 短文本分类、情感判断这类输出空间很小、决策边界很宽的任务。
- 摘要、改写这类有多个可接受答案的生成任务。
- 闲聊、陪伴类对话,用户对措辞差异的容忍度本来就高。
这个规律能帮你做先验判断——决定要不要花力气去测、以及重点测什么。但它不能替你得出结论。
具体损失多少,只有拿你自己的任务测了才知道。本文不给任何百分比,因为给了也不可信。 同一个量化方案,在别人的评测集上表现好,不代表在你的提示词模板、你的输入分布、你的采样参数下也一样。这不是保守,是这类数字本身就没有跨场景的可迁移性。
三、本文的核心:一套你自己能跑完的评测流程
这一节是全篇真正有价值的部分。整个流程半天到一天能跑完,跑完之后你手里就有了自己的数字,从此不需要再看任何人的跑分。
第一步:先定义验收标准,在测之前写下来
顺序不能反。 必须在看到任何结果之前,把「什么算通过」写成文字并存档。
原因很实际:先测后定标准的话,你会不自觉地把标准调整到「刚好让当前结果通过」的位置。这是人之常情,但它会让整个评测失去意义。
标准必须是可量化的。举几个可以直接用的形式:
- 结构化输出场景:格式合法率 ≥ X%(能被解析器成功解析的比例,程序自动判定)
- 分类抽取场景:准确率 ≥ X%(和人工标注的标准答案比对)
- 开放生成场景:人工抽检通过率 ≥ X%(固定抽样数量,固定评分细则,最好两个人独立打分)
- 兜底红线:严重错误零容忍,比如捏造关键数字、输出敏感内容,出现一例就直接否决
X 填多少由你的业务定,我不替你定。但它必须是一个具体数字,不能是「基本没问题」。没有标准的对比就是各说各话——一方说「我觉得还行」,另一方说「我觉得变差了」,最后靠谁嗓门大来决定要不要上线。
第二步:准备一个固定的评测集
用你真实业务的样本,不要用公开 benchmark。 公开评测集测的是通用能力,你上线要交付的是特定任务,两者的相关性远比想象中弱。
几个要点:
- 数量上先求覆盖再求规模。把你线上实际出现过的输入类型都覆盖一遍,比堆一千条同质样本有用。
- 一定要包含边界样本:超长输入、字段缺失、格式不规范、多语言混排、历史上真实翻过车的那些请求。量化带来的退化最先出现在边界上,只测顺风样本你什么都测不出来。
- 评测集固定下来之后就版本化存起来,别改。以后每次换模型、换精度、换框架版本都用同一批输入,横向才可比。这个评测集会成为你团队最有价值的资产之一,比任何一次评测结论都值钱。
第三步:同一批输入,跑 FP16 基线和目标量化档
关键在于除了精度这一个变量,其他全部固定:
- 固定随机种子。
- 固定采样参数——温度、top-p、最大生成长度、停止条件全部一致。做质量对比时建议把温度压到最低(贪心解码),把随机性从等式里拿掉。否则你测的是随机性,不是量化。
- 固定提示词模板,一个字都不改。
- 固定框架和框架版本,同一台机器上跑。
这一步最常见的翻车是:换精度的同时顺手升级了框架版本,或者改了个 batch 参数,最后差异出来了却说不清是哪个因素造成的。一次只动一个变量。
第四步:按验收标准打分,同时记录显存和吞吐
质量、显存、吞吐三个数要在同一次实验里一起拿到,否则你后面没法算账。
- 显存:记录稳态占用,以及并发压到目标水平时的峰值。
- 吞吐:记录你实际关心的那个指标(每秒输出 token 数、单请求端到端耗时、或固定时间内完成的请求数),口径自己定但要前后一致。相关的口径讨论可以看推理吞吐怎么衡量。
- 质量:严格按第一步写下的标准打分,不要临场放宽。
第五步:算账
把省下来的显存换算成实际收益:是少用了一张卡,还是同样的卡多扛了一倍并发,或者是每千次请求的成本降了多少。然后问一句:这个收益,值不值第四步测出来的那个质量差?
这个问题没有通用答案,但有了三个数之后,它至少变成了一道可以摆到桌面上讨论的题,而不是一场谁也说服不了谁的争论。
结果记录表模板
跑完直接填这张表,一页纸就能拿去开会:
| 精度档 | 显存占用(稳态/峰值) | 吞吐 | 验收通过率 | 结论 |
|---|---|---|---|---|
| FP16(基线) | 基准 | |||
| FP8 / INT8 | ||||
| INT4 |
补充几列会更好用:测试日期、框架版本、评测集版本、采样参数、备注(失败样本的典型形态)。尤其是最后一列——如果 INT4 掉下来的那些样本全是同一类(比如全是超长输入),那你可能不需要放弃量化,只需要给这类请求单独走一条高精度路线。这个洞察从汇总数字里是看不出来的,只能从失败样本的形态里看出来。
四、量化不是唯一的显存旋钮,而且它该排在最后
这是本文最重要的一个判断。
在推理框架层面,能影响显存的参数不止量化一个。以 vLLM 的官方优化文档为例,和显存直接相关的参数包括 gpu_memory_utilization(提高它可以给 KV cache 更多空间)、max_num_seqs(一批里的并发请求数上限,调小会减少并发从而需要更少的 KV cache 空间)、max_num_batched_tokens(单批次最大 token 数,影响 prefill 与 decode 的平衡)、max_model_len(限制单个序列的最大 token 数)、tensor_parallel_size(把权重切分到多张 GPU,使每张卡有更多显存留给 KV cache)、pipeline_parallel_size(把模型层分布到多张 GPU,降低每张卡上权重所需显存),以及 kv_cache_memory(直接指定 KV cache 大小,跳过显存 profiling 阶段)。
这些参数的默认值本文一个都不写,官方文档没有明确给出,以你所用版本的官方文档当次为准。
vLLM 官方文档里针对 OOM 和「not enough KV cache space」给出的缓解顺序是:提高 gpu_memory_utilization → 降低 max_num_seqs 或 max_num_batched_tokens → 提高 tensor_parallel_size(代价是同步开销)→ 提高 pipeline_parallel_size(代价是延迟)。
值得注意的是这份官方顺序里没有量化。这不是疏漏,而是反映了一个本质区别:
调框架参数和加卡,损失的是吞吐或延迟;量化,损失的是质量。 前者的代价可以在监控里直接看到、可以随时回滚、不会污染输出;后者的代价是隐性的、间歇性的,需要专门的评测才能发现。
所以我给的决策顺序是:
- 先调框架参数。降低
max_model_len到你业务真正需要的长度(很多团队开着一个远超实际需求的上下文长度,白白锁掉大量 KV cache 空间);调整max_num_seqs匹配你真实的并发;调整gpu_memory_utilization。这一步零质量损失,改配置重启就能验证,也能随时改回来。 - 再考虑多卡。张量并行或流水线并行,代价是同步开销或延迟,但输出质量不变。成本上升是明确可算的,不确定性低。
- 最后才考虑量化。只有当前两步都试过、仍然不满足需求时才动它,而且必须配合第三节那套评测流程一起做。
这个顺序的逻辑就是:先用掉所有不损失质量的手段,再动会损失质量的那个。 别反过来——我见过太多团队第一反应就是量化,把最有风险的选项排在了最前面,而那个只需要把 max_model_len 从一个夸张的值调到实际需求就能解决的问题,一直没人去看。
五、什么时候量化明确划算,什么时候别碰
明确划算的情况:
- 显存就差一点点。装不下和装得下之间只隔着几个 GB,量化让你从「跑不起来」变成「跑起来了」。这时候质量的边际损失对比可用性的跃迁,几乎一定划算。
- 离线批处理。没有实时用户,结果可以先落库再抽检,出问题可以重跑。容错窗口大,试错成本低。这类场景本来就适合优先压成本。
- 你已经测过,并且确认损失可接受。这是最理直气壮的一种——你有自己的数字。
- 任务本身在不敏感区间,比如短文本分类,而且你用真实样本验证过。
别碰的情况:
- 质量要求严格,同时没有评测能力。 这是最危险的组合。没有评测集、没有验收标准,量化上线之后你既发现不了退化,也说不清退化的原因。真出了问题,回滚的时候你甚至不确定是不是量化造成的。这种状态下,量化省下的那点显存钱,远远抵不过一次线上事故的排查成本。
- 瓶颈根本不是权重显存。上面第一节讲过,你缺的是 KV cache 就去调 KV cache 相关的旋钮,别绕远路。
- 框架参数还没调过一轮。 免费的方案还没用完,没必要先付费。
- 正在同时排查其他问题时。 别在系统不稳定的时候引入新变量,你会分不清哪个是因哪个是果。
如果这一轮评估下来,自建的总成本和运维负担让你开始动摇,那说明真正该重新算的是自建与 API 的那笔账,可以看自建推理还是直接调 API。至于量化格式本身的技术差异和框架适配问题,另有一篇模型量化格式对比专门讲。
决策清单
- 先定位瓶颈:是权重装不下,还是 KV cache 不够?前者量化直接命中,后者收益有限。搞错这一步,后面全白做。
- 权重显存自己算:参数量 × 每参数字节数(FP16 是 2、INT8 是 1、INT4 是 0.5),单位口径先定死(GB 还是 GiB)。这一步不需要任何实验。
- 框架参数先调一轮:
max_model_len、max_num_seqs、gpu_memory_utilization,零质量损失,可随时回滚。参数默认值以官方文档为准。 - 多卡排在量化之前:张量并行、流水线并行的代价是吞吐和延迟,不是质量。
- 在测之前写下验收标准:可量化、有具体数字、存档不改。顺序反了整个评测就废了。
- 评测集用真实业务样本:覆盖边界样本,版本化保存,以后所有对比都用它。
- 对比时只动精度一个变量:固定种子、固定采样参数、固定提示词、固定框架版本。
- 不要采信任何来路不明的量化跑分,包括本文没有给的那些——量化能不能上,只有你自己的评测集说了算。