🏠 总目录📚 本教程 量化 ← →
📑 本页目录(点开跳转)

18 · 量化

⏱ 32 分钟 | ⭐ 推理侧性价比最高的优化


🎯 一句话

推理是带宽瓶颈(第 15 章),而量化直接把要搬的数据减半。 所以它不只是"省显存" —— 它直接让解码速度翻倍。 这就是为什么量化在推理侧的地位远高于训练侧。

FP16原始权重:连续的、几乎无限多个取值INT8量化后:只能落在这些格点上 —— 每个数被「吸」到最近的格子量化 = 把连续的权重塞进有限个格子⭐ 关键是【缩放因子】选多大:格子铺太宽浪费精度,铺太窄两头被截断⚠️ 离群值是最大的敌人 —— 一个极端权重会把整组的格子撑开,其余全挤在中间
每个连续权重被「吸」到最近的格点上。⭐ 关键是缩放因子选多大:铺太宽浪费精度,铺太窄两头被截断。⚠️ 离群值是最大的敌人 —— 一个极端权重会把整组格子撑开,其余全挤在中间。

📉 一、为什么推理侧收益特别大

算一算

回忆第 4 章的心算公式:

解码速度 = 显存带宽 ÷ 模型大小

7B BF16(14GB)在 A100:2000/14 ≈ 143 tok/s

7B INT8(7GB): 2000/7 ≈ 286 tok/s ⭐ 直接翻倍

7B INT4(3.5GB): 2000/3.5 ≈ 571 tok/s ⭐ 再翻倍

操作步骤

⭐ 三重收益:
① 解码速度翻倍(带宽瓶颈直接受益)
② 省下的显存能开更大 batch→吞吐再涨
③ 更小的模型能塞进更便宜的卡

🔑 对比训练侧:训练是算力瓶颈,量化省下的带宽收益有限, 而且低精度会影响梯度和收敛。所以训练最多用到 BF16/FP8,推理能到 INT4。


🔢 二、量化的基本原理

$$q = \text{round}\left(\frac{x}{s}\right) + z, \qquad x \approx s\,(q - z)$$

(s = scale 缩放因子,z = zero point 零点)

结果对照

把 FP16 的一组数映射到 INT8 的 [-128, 127]
例:一组权重范围 [-0.5, 0.5]
s = 1.0/255 ≈ 0.0039
0.3→round(0.3/0.0039) = 77→还原 0.3003 ✅

两个关键选择:

选择 选项 说明
对称 vs 非对称 z=0 / z≠0 对称更快,非对称更准(分布不对称时)
粒度 per-tensor / per-channel / per-group ⭐ 粒度越细越准,元数据越多

对照

⭐ per-group(如每 128 个权重一组一个 scale)是现在的主流:

精度接近 per-channel,开销可接受


😖 三、离群值:LLM 量化的核心难题

信息关系

⭐ 关键发现:LLM 的激活值里有【极少数】维度的值特别大
(比其他维度大 100 倍以上)
如果用一个 scale 覆盖整个张量,
为了容纳离群值,scale 必须很大
正常的值全被压到很少的几个量化格子里→精度崩溃 💀

信息关系

激活值分布示意:
维度: 0 1 2 3 · 1024 · 4096
值: 0.3 0.2 -0.4 0.5 【87.2】 0.1
↑ 离群值
scale 必须按 87.2 定→0.3 和 0.2 量化后可能变成同一个数

三种主流解法:

方法 思路
LLM.int8() 把离群维度单独用 FP16 算,其余 INT8
SmoothQuant ⭐ 把激活的难度"转移"给权重:激活除以 s、权重乘以 s,数学等价但两边都好量化
AWQ ⭐ 发现只有 1% 的权重重要,按激活幅度找出它们并保护

🧰 四、主流方法怎么选

先分清两条路:PTQ 和 QAT

上面讲的 LLM.int8()、SmoothQuant、AWQ、GPTQ 全都是 PTQ(训练后量化)。 还有一条路叫 QAT(量化感知训练)—— 先说结论:LLM 时代 PTQ 是绝对主流,你大概率不会用到 QAT。

PTQ(训练后量化) QAT(量化感知训练)
什么时候量化 模型训完之后,直接压 训练过程中就模拟量化误差,让模型自己适应
要什么 一个校准集(几百条样本)⭐ 完整的训练管线 + 数据 + 算力
代价 几分钟到几小时,一张卡就行 一次(微调级别甚至预训练级别的)重训 💀
精度 到 INT4 已经够用 更低比特(INT2/INT3)时优势明显
谁在用 ⭐ 几乎所有 LLM 部署 端侧小模型、CV、语音

⭐ 为什么大模型时代 PTQ 一边倒:QAT 要重训。 一个 70B 模型重训一遍的成本,和"量化后掉的那 1 分"完全不成比例 —— 而且你多半根本拿不到它的训练数据。 反过来,PTQ 只要几百条校准样本、一张卡、几十分钟,效果已经能到 INT4 几乎无损。 正是因为 PTQ 在 LLM 上够用了,这几年的研究才全都堆在 PTQ 这一侧(AWQ、GPTQ、SmoothQuant 都是)。

⚠️ PTQ 的代价藏在"校准集"里:

因果链

校准集是用来【统计激活值的分布范围】的(定 scale 用)
⚠️ 如果校准集的分布和你的线上流量对不上:
比如用英文维基校准,线上跑的是中文客服对话
scale 定错了→离群值的位置也判错了
量化后在【你的场景】上掉得比公开榜单严重得多 💀
⭐ 做法:校准集直接从【自己的线上日志】里抽,几百条就够

💡 这也解释了一个常见困惑:为什么别人测的"AWQ 几乎无损",到我这里就掉了? 很可能不是方法的问题,是校准集不是你的分布。

权重量化(最常用)

方法 精度 特点
GPTQ INT4/INT3 逐层用二阶信息校准,需要校准集,质量好
AWQ ⭐ INT4 激活感知,保护重要权重,快且质量好
GGUF / llama.cpp INT2~8 CPU/边缘部署的事实标准
bitsandbytes NF4 4bit QLoRA 用的,适合微调场景

量化类型对比

类型 权重 激活 收益 说明
W8A16 INT8 FP16 带宽减半 ⭐ 最稳,几乎无损
W4A16 ⭐ INT4 FP16 带宽 1/4 当前性价比最高
W8A8 INT8 INT8 带宽+算力 需要 SmoothQuant 类方法
FP8(W8A8) ⭐ FP8 FP8 带宽+算力 H100 上首选,硬件原生支持

⭐ 实践建议: - 有 H100 → 用 FP8(硬件支持,几乎无损,算力也翻倍) - A100 及以下 → 用 AWQ / GPTQ 的 W4A16 - 要极致压缩 / CPU 部署 → GGUF

# 🧩 骨架:`LLM` 来自你自己的代码,这一段只看写法
# vLLM 加载量化模型:通常不用改代码
llm = LLM(model="TheBloke/Llama-2-7B-AWQ", quantization="awq")
llm = LLM(model="...", quantization="fp8")            # ⭐ H100
llm = LLM(model="...", kv_cache_dtype="fp8")          # ⭐ KV 也量化

⚠️ 五、质量评估:这一步不能省

操作步骤

  1. ⚠️ 量化最危险的地方:【它不会报错】
  2. 模型照常输出,看起来也通顺 —— 但某些能力悄悄退化了
  3. ⭐ 必须测这三层:
  4. 困惑度(PPL)—— 最快的 sanity check,但【不敏感】
  5. 下游任务基准 —— MMLU、GSM8K、HumanEval
  6. ⭐ 你自己的业务数据 —— 最重要

💥 一个真实的现象:量化对不同能力的伤害是不均匀的。 常见的观察是:闲聊质量几乎不变,但数学推理和代码生成明显下降 —— 因为后者需要精确的多步计算,误差会累积。

所以"PPL 只涨了 0.1"不能作为通过的依据。 必须测你真正在用的能力。

# 🧩 骨架:`base` 来自你自己的代码,这一段只看写法
# ⭐ 最小可行的质量对照
for name, model in [("fp16", base), ("awq", quant)]:
    print(name, evaluate(model, my_business_testset))
    # 至少 200 条真实样本,人工看 20 条

🧊 六、别忘了 KV Cache 量化

关键信息

⭐ 权重量化省的是【固定】的那部分显存
KV Cache 量化省的是【随 batch 增长】的那部分
高并发场景下,KV Cache 才是显存大头(第 16 章)
两者都要做

结果对照

7B 模型,A100 80G,seq=2048:
FP16 权重 + FP16 KV:14GB + 每请求 1.07GB→约 60 并发
INT4 权重 + FP8 KV: 3.5GB + 每请求 0.53GB→约 144 并发 ⭐ 2.4 倍

🔗 和站内其他章的关系

相关的地方 这里的位置
第 4 章 带宽÷模型大小 量化提速的直接依据 ⭐
第 15 章 推理是带宽瓶颈 为什么推理侧收益大
第 6 章 混合精度 同一思路的温和版
第 16 章 KV Cache KV 量化
第 9 章 QLoRA 训练侧的量化应用
《大模型全景导论》06 推理优化 量化的三个真实代价 那边给部署视角的取舍清单,本章给"离群值"这个根因 ⭐
《模型上线之后》17 版本回溯与可复现 黄金样本 量化完就是一个新版本;本章第五节说的质量评估,最省事的做法就是那套黄金样本 ⭐
《推荐算法》10 向量检索与 ANN PQ / OPQ 同一个思想的另一个战场:float32 压成码本、内存降 32 倍,换的也是精度

✅ 检查点

  1. 为什么量化在推理侧的收益远大于训练侧?
  2. 7B 模型从 BF16 量化到 INT4,解码速度理论上变多少?
  3. 量化的三重收益是什么?
  4. 什么是离群值问题?为什么它对 LLM 特别严重?
  5. SmoothQuant 和 AWQ 的思路分别是什么?
  6. PTQ 和 QAT 的区别是什么?为什么大模型时代 PTQ 一边倒?PTQ 的代价藏在哪里?
  7. W4A16 和 W8A8 的区别?有 H100 该用什么?
  8. 为什么说"量化最危险的地方是它不会报错"?
  9. 量化对哪类能力伤害更大?这对评估有什么要求?
  10. 权重量化和 KV Cache 量化各省什么?
👀 答案
  1. 因为推理是带宽瓶颈,量化直接减少要搬的数据 → 解码速度直接翻倍;而训练是算力瓶颈,带宽收益有限,且低精度影响梯度和收敛。所以训练最多 BF16/FP8,推理能到 INT4。
  2. 解码速度 = 带宽÷模型大小。14GB → 3.5GB,速度约 4 倍(143 → 571 tok/s)。
  3. ①解码速度翻倍 ②省下的显存能开更大 batch,吞吐再涨 ③更小的模型能塞进更便宜的卡。
  4. LLM 的激活值里极少数维度的值比其他大 100 倍以上。用一个 scale 覆盖整个张量时,为了容纳离群值 scale 必须很大,正常值全被压到很少的格子里,精度崩溃。
  5. SmoothQuant:把激活的难度转移给权重——激活除以 s、权重乘以 s,数学等价但两边都好量化。AWQ:发现只有 1% 的权重重要,按激活幅度找出并保护它们。
  6. PTQ 是模型训完之后直接压(只要几百条校准样本、一张卡、几十分钟);QAT 是在训练过程中就模拟量化误差让模型自己适应(要完整训练管线 + 数据 + 算力,等于重训一次)。大模型时代 PTQ 一边倒是因为 QAT 要重训——70B 重训一遍的成本和"掉的那 1 分"完全不成比例,而且多半拿不到训练数据;而 PTQ 到 INT4 已经够用。PTQ 的代价藏在校准集里:⚠️如果校准集分布和线上流量对不上(用英文维基校准、线上跑中文客服),scale 和离群值位置都会判错,在你的场景上掉得比公开榜单严重得多——校准集要从自己的线上日志里抽。
  7. W4A16 权重 INT4、激活 FP16(只省带宽);W8A8 两者都 INT8(省带宽也省算力,但需要 SmoothQuant 类方法)。有 H100 该用 FP8——硬件原生支持,几乎无损,算力也翻倍。
  8. 因为模型照常输出、看起来也通顺,但某些能力悄悄退化了——没有任何报错提示你。
  9. 数学推理和代码生成伤害更大(需要精确的多步计算,误差会累积),闲聊质量几乎不变。要求:"PPL 只涨 0.1"不能作为通过依据,必须测你真正在用的能力和自己的业务数据。
  10. 权重量化省固定的那部分显存;KV Cache 量化省随 batch 增长的那部分。高并发下 KV Cache 是大头,两者都要做。

🛑 可以停在这里

⚡ 走神救援

⭐ 推理是带宽瓶颈,量化直接把要搬的数据减半——所以它不只是省显存,是让解码速度成倍地涨。 这也是它在推理侧地位远高于训练侧的原因:训练是算力瓶颈、低精度还影响收敛。⭐ 三重收益:解码变快、省下的显存能开更大 batch、能塞进更便宜的卡。

😖 ⭐ 核心难题是离群值:激活里极少数维度比其他大两个数量级,一个 scale 要容纳它就必须很大,于是正常值全被压进很少的格子里,精度崩溃。三个解法的思路各不相同:把离群维度单独留高精度、把激活的难度按数学等价的方式转移给权重、⭐ 只保护那百分之几真正重要的权重——而重要性看的是激活幅度,不是权重本身多大。

⭐ 两条路要分清:训完之后压(几百条校准样本、一张卡、几十分钟)和训练时就模拟量化误差(等于重训一次)。 上面那些方法全属于前者,⭐ 大模型时代也是前者一边倒——重训一遍的代价和掉的那一点分完全不成比例,而且你多半拿不到训练数据。

⚠️⭐ 它的代价藏在校准集里:校准集分布和线上流量对不上,scale 和离群值位置就都判错,在你的场景上掉得比榜单严重得多。⭐ 处方是校准集直接从自己的线上日志里抽,几百条就够——「别人说几乎无损、到我这里就掉」多半是这个原因。

⚠️⭐ 质量评估不能省,因为量化最危险的地方是它不会报错:模型照常输出且通顺,能力却悄悄退化。💥 而且伤害不均匀——闲聊几乎不变,数学推理和代码生成明显下降(多步计算误差累积)。⭐ 所以困惑度只涨一点点不能作为通过依据,必须测自己的业务数据。

⭐ 最后别忘了 KV Cache 量化:权重量化省的是固定那部分,KV 量化省的是随 batch 增长的部分——高并发下后者才是大头。

下一节 👉 18b-知识蒸馏.md

打卡记录保存在你的浏览器里,首页能看到总进度