本地跑模型时最常见的卡点:显存不够,要么降并发、要么换小模型、要么上量化。量化能省显存,但省下来的代价在哪、哪个任务先崩、上线前怎么验,很多人是出事才发现。这篇给一套按显存和目标吞吐反推档位的算法,加上一份上线前的验证清单。
本地跑模型最常撞的墙就是显存不够。三条路:降并发、换更小的模型、上量化。前两条直接砍能力,量化看起来最划算——权重字节数直接减半甚至减到四分之一。但省下来的显存是从哪抠出来的,很多人是上线之后才发现问题。
这篇不讲原理史,只给一套能落地的算法:先定任务容错等级,再按显存和目标吞吐反推档位,最后过一遍上线前的验证清单。你按顺序走一遍,至少能避开「压完显存够了、结果格式全崩」这类典型翻车。
量化到底动了什么:把权重和激活的数值精度压下来
先说清楚一件事:量化不是单一开关,它是几个可以独立开关的动作。把它们混着讲,后面就没法排查问题了。你压了权重没压激活,和两个都压,出问题的位置完全不一样。
- 权重量化
- 把模型参数从高精度压成低精度存储,省的是常驻显存,对输出的影响最直接。
- 激活量化
- 把前向计算中间产生的数值也压精度,省显存的同时通常提速更明显,但更容易出精度问题。
- KV Cache 量化
- 只压推理时缓存的键值,不动模型本身,长上下文场景省得最多,对质量影响相对可控。
- 离群值处理
- 激活里总有少数特别大的值,按通道或按组缩放能少损失一点,这也是同叫一档但质量差很多的原因。
精度损失主要发生在数值分布的长尾:那些异常大的激活值被截断,而那些本来就很小、但决定了细微判断的差异被抹平。所以同一个档位标签下,不同实现、不同缩放策略,结果可以差很远。别把档位名当成统一标准,它只是个粗略分类。
哪类任务最先崩:按容错度给任务排队
低档量化不是均匀地让所有任务变差,而是按任务的容错度排队崩。理解这个顺序,你就能预判自己会不会踩坑。
| 任务类型 | 容错度 | 低档量化的典型表现 |
|---|---|---|
| 结构化输出、JSON 字段、函数调用 | 低 | 字段名拼错、引号缺失、schema 校验失败 |
| 代码补全、精确改写 | 低 | 变量名漂移、括号不匹配、逻辑看似对但跑不通 |
| 长上下文检索、多轮指代 | 中低 | 答案错得不明显但稳定错,换个问法还是错 |
| 数学步骤推演、多步推理 | 中低 | 中间步骤悄悄失真,最终答案偏掉 |
| 口语对话、摘要、翻译 | 中高 | 读起来通顺,语义基本在,偶有措辞变化 |
判断方法很简单:把你的任务拆成「答案唯一」和「意思到了就行」两类。前者别压太狠,哪怕显存吃紧也先想别的办法;后者是低档量化最安全的落脚点。
- 会有下游程序解析你输出的,一律按低容错处理;
- 有标准答案可以自动对错的,按低容错处理;
- 输出长度很长、格式很复杂的,优先怀疑量化而不是怀疑提示词;
- 纯给人看、没有程序解析的,可以放心试低档;
- 不确定属于哪类时,按低容错处理,验证通过再降。
显存怎么算:权重、KV Cache、激活三块分开估
显存估算出错的根源,通常是只算了权重。实际占用是三块:权重、KV Cache、运行时的临时激活和碎片。长上下文场景里,KV Cache 经常比权重还大。
| 组成 | 大致怎么算 | 受什么影响 |
|---|---|---|
| 权重 | 参数量 × 每参数字节数,再加缩放参数和框架开销 | 模型大小、量化档位 |
| KV Cache | 并发数 × 上下文长度 × 每 token 缓存字节数 | 并发、上下文长度、是否压 KV |
| 激活与碎片 | 前向计算的临时张量、显存碎片 | 批次大小、序列长度、显存分配策略 |
按档位说,高精度每参数大约两字节,中档约一字节,低档约半字节,这是粗略量级,实际还要加上缩放参数和运行时开销。别按理论值把显存卡满,留出余量给临时激活和碎片。
- 先查目标卡型的硬指标确认显存容量和带宽,带宽决定解码速度上限。到 /compute/gpus 对照当时的卡型参数,别凭记忆。
- 用现成测算对一遍站内 /models/deploy 有部署测算入口,先拿现成数字估一遍,和你自己算的对照看差距在哪。
- 把 KV Cache 单独拎出来算按「并发 × 上下文长度 × 每 token 缓存」估,如果它占比超过权重,说明光压权重意义不大。
- 留余量再下结论在估算值上留出一部分余量,再判断这个档位加这个并发到底塞不塞得下。
吞吐这笔账:量化省显存,但不一定更快
很多人默认「精度低 = 速度快」,这在解码阶段通常成立,因为显存带宽是主要瓶颈,权重字节数变小,读得就快。但这条规律有前提,踩破前提就会反过来。
低档量化往往需要反量化操作,或者依赖特定的加速 kernel。在小批量、短序列的场景下,这部分额外开销可能盖过省下来的带宽收益,出现「省了显存反而变慢」的情况。所以别只看单序列延迟,要看总吞吐。
- 并发才是吞吐的关键变量:省下的显存拿去开更多并发,总吞吐才会明显上去;
- 单序列延迟和总吞吐是两个指标,优化方向可能相反;
- 小批量短序列先测基线,别默认降档一定提速;
- 先跑基线再调档,没有基线就没有对照,调完也不知道是变好还是变差。
- 到 /tools/speed-test 量出当前延迟与吞吐,把基线记下来再动档位。
量化省的是显存,不是自动省时间;把省下的显存换成并发,才是吞吐的正解。
按显存和目标吞吐反推档位的操作顺序
- 定任务容错等级用上一节的表判断你的任务属于哪一档,低容错的任务直接排除最低档位。这一步决定的是可选范围,不是最终选择。
- 算目标并发下的显存需求把权重、KV Cache、预留三块加起来,看目标并发需要多少显存。这一步决定的是能不能塞下。
- 从高到低试档位,先满足显存优先保住质量,从容错范围内最高的档位往下试,第一个能塞下的档位就是候选,不要一上来就压到最低。
- 显存够但吞吐不够时,加并发开连续批处理、提高并发上限,通常比继续降精度划算,而且不损失质量。
- 显存不够但吞吐够时,先减别的依次考虑减并发、缩上下文,再考虑降档,最后才换更小的模型。换模型对能力的损失通常最大。
不适用的情况要说清楚:如果你的任务要求严格可复现的输出,比如做对拍、做回归测试、做确定性校验,任何有损量化都会让结果不稳定,必须先把验证做完再上,不能拿它当基准。
上线前的验证步骤:别只看一两个样例
量化验证最容易犯的错,是拿几个顺手的问题试一下,觉得「读起来还行」就上了。低档量化的退化往往藏在长尾和格式细节里,随手试根本试不出来。
- 准备固定评测集从真实流量里抽几十到上百条,覆盖边界输入、超长输入、格式要求严格的输入。每次换档位都跑同一份,保证可比。
- 定义可量化的对比维度至少包含格式合规率、关键字段准确率、拒答率。只写「通顺不通顺」这种主观判断,等于没验证。
- 自动指标 + 人工交叉抽样自动指标对量化的退化常常不敏感,尤其是长输出任务。抽一部分人工看,重点看输出结尾和格式部分。
- 和基线逐项对比和降档前的同档位输出做逐条对照,标出退化条目,判断退化是否落在可接受范围。
- 接入监控再放量用 /tools/quality-check 做上线前检查,用 /tools/quality-monitor 把上线后的退化监控起来。
上线后的兜底:灰度、回滚与监控
验证通过不等于万事大吉,量化模型在真实流量分布下的表现可能和评测集不一样。上线阶段要给自己留退路。
- 先切一小部分流量到低档位,观察一段时间再逐步放量,别一次性全量替换;
- 保留一档更高的精度作为回滚目标,切换过程不要依赖客户端改动;
- 给质量指标设告警阈值,格式解析失败率、重试率、人工返工率通常比评分更早报警;
- 用量和成本变化到 /usage 与 /price-watch 对一遍,确认省下的成本和损失的质量是否划算。
回滚路径这件事要提前想清楚。如果切档位需要改客户端、改配置、走一遍发布流程,那真出事的时候你就没法快速退回去。理想状态是一个开关就能切换。
什么情况下不该压:几个明确的排除条件
不是所有场景都值得压。下面这几条命中任意一条,优先考虑别的方案,而不是硬上低档量化。
| 情况 | 为什么不压 | 更该做什么 |
|---|---|---|
| 任务精度极度敏感、失败率不可接受 | 低档量化的退化不可控 | 选更高精度档位,或换更适配的模型 |
| 上下文极长且并发要求高 | KV Cache 才是大头,压权重杯水车薪 | 先算 KV Cache 的账,考虑压 KV 或缩上下文 |
| 团队没有评测集、也没人力抽检 | 降档后无法判断是否变差 | 先补评测能力,再谈降档 |
| 许可证与商用条款有限制 | 部署方式可能不合规 | 到 /models 与 /inference 核对部署与授权口径 |
最后提醒一句:模型资料、卡型参数、部署授权这些信息会变,别拿记忆里的数字做决策。具体到 /models 与 /inference 核对当下的口径,再回到 /compute/gpus 确认硬件条件。
下一步先量出你的基线延迟与吞吐,再按显存算法反推档位,最后跑一遍质量验证清单。三个入口都在站内,走完再决定压不压、压到哪一档。→常见问题
INT4 的效果一定比 INT8 差很多吗?
不一定,取决于任务和实现。从容错度高的生成任务看,两者的体感差距常常很小;但在结构化输出、代码、数学这类任务上,低档位的退化会更明显也更稳定。判断办法是拿你自己的评测集各跑一遍,而不是看别人的对比结论。
显存不够,是先降精度还是先减并发?
先看瓶颈在哪。如果显存主要被 KV Cache 吃掉,减并发或缩上下文更直接;如果权重本身就装不下,那只能降精度或换模型。顺序建议是:缩上下文、减并发、降精度、换模型,越往后对效果的影响越大。
量化之后速度变慢了,正常吗?
常见。低精度权重需要额外的反量化或专用 kernel 支持,在批量小、序列短的场景里,这部分开销可能比省下的带宽收益更大。解决办法通常是加大批量、开启连续批处理,或者换一套对该档位有优化的推理框架。
怎么判断量化后质量掉了?
建一份从真实流量抽出来的固定评测集,每次换档位跑同一份,重点看格式合规率、关键字段准确率、拒答率这些可数的指标,再配合人工抽样看长输出。只靠肉眼读几个样例,几乎一定会漏掉退化。
量化档位选好之后还需要再调吗?
需要。模型版本、推理框架、并发配置变化后,原来的档位结论可能不再成立。建议把档位当成一个配置项,和评测集一起版本化,每次改动都重跑一遍验证流程。