学习手册 / 量化与推测解码课程官网 ↗

CHAPTER 11 / 推理与系统

量化与推测解码

一种减少表示成本,一种减少串行等待,分别验证收益。

进阶建议阅读 35 分钟,练习另计自编配套教程
读完这一章,你应该能
  • 解释权重、激活和 KV 量化的区别及误差来源
  • 理解推测解码的草稿、验证与拒绝修正
  • 选择质量和性能对照实验,避免把理论容量当成真实加速

量化是在改变数值表示

模型中的权重和中间状态通常以浮点数表示。量化使用更少位数或不同数值格式表示它们,以降低存储和数据搬运成本。一个简单的对称整数例子是 q = round(x / scale),读取时近似恢复为 x̂ = scale × q。有限整数范围意味着舍入误差,也可能发生截断;缩放因子的粒度影响不同数值之间如何共享动态范围。

要问清量化对象。权重量化压缩模型参数,激活量化影响运行中的中间数值,KV 量化压缩随上下文增长的缓存。W4A16 通常描述四位权重、十六位激活,并不自动说明 KV 也只有四位。缩放元数据、部分保留高精度的层以及内核临时空间都会增加实际占用。

理论内存收益不等于加速比例

假设模型有七十亿个参数,每个参数十六位,纯权重数据约为 14 GB;改为四位后理论数据量约为 3.5 GB,这里 GB 使用十进制。实际文件和显存还包括缩放因子、零点、元数据及未量化部分。即使权重变成四分之一,总显存也不一定变成四分之一,因为 KV 与运行时空间可能保持不变。

低位表示有机会减轻带宽或容量瓶颈,但是否更快取决于硬件指令、内核实现、反量化开销、批大小和模型结构。不能假定所有设备都高效支持同一种格式。部署时按实际 vLLM 版本的兼容列表选择,再测真实任务。质量评估需要包含数字、代码、长上下文等你的关键场景;只看一句聊天是否通顺很容易漏掉退化。

本机实验:把舍入误差算出来

下面用 Python 标准库演示四位与八位对称量化。这只是用一组权重数值演示量化重建误差,不是端到端推理;它没有运行语言模型或 GPU 内核,也不代表 AWQ、GPTQ 等实际算法。保存为 quant_lab.py 后运行,只比较重建误差和理论权重大小。

from math import sqrt
values = [-1.0, -0.37, 0.04, 0.29, 0.83]
def quantize(xs, bits):
    if not xs:
        raise ValueError("xs must contain at least one weight")
    if not isinstance(bits, int) or bits < 2:
        raise ValueError("bits must be an integer >= 2")
    peak = max(abs(x) for x in xs)
    if peak == 0:
        return [0.0] * len(xs), 0.0
    limit = 2 ** (bits - 1) - 1
    scale = peak / limit
    quant = [max(-limit, min(limit, round(x / scale))) for x in xs]
    restored = [q * scale for q in quant]
    rmse = sqrt(sum((x-y)**2 for x, y in zip(xs, restored)) / len(xs))
    return restored, rmse

for bits in (4, 8):
    restored, error = quantize(values, bits)
    print(bits, [round(x, 4) for x in restored], "RMSE", round(error, 6))
    print("7B raw weight GB", 7_000_000_000 * bits / 8 / 1e9)
assert quantize(values, 8)[1] < quantize(values, 4)[1]
assert quantize([0.0, 0.0], 4) == ([0.0, 0.0], 0.0)
try:
    quantize([], 4)
except ValueError:
    pass
else:
    raise AssertionError("empty weights should be rejected")

把某个数改成 100,观察其他小数如何受到统一 scale 的影响,这体现了异常大值与动态范围问题。再尝试把数列分成两组分别量化,比较误差与新增缩放元数据。这个实验解释表示误差,不能用于预测语言任务成功率。

空数组没有可定义的误差统计,因此函数明确抛出 ValueError;全零权重直接返回零数组和零误差,避免缩放因子为零导致除零。

推测解码先写草稿,再由目标模型验证

普通自回归 decode 每一步通常只确认下一个 token。推测解码先让便宜的草稿机制连续提出几个候选,再让目标模型并行检查这些位置。有些候选被接受,于是一次目标模型执行可以推进多个 token;一旦拒绝,就按算法修正当前位置并重新开始。草稿可以来自小模型或其他候选生成机制,不要求只有一种实现。

经典精确采样算法中,目标分布记为 p,草稿分布记为 q,候选 x 的接受概率是 min(1, p(x)/q(x))。拒绝时从归一化后的 max(p−q, 0) 分布重采样,才能保持目标采样分布。这里省略了多 token 迭代的边界处理,不能把它当作完整实现。直接“接受看起来合理的草稿”不具备同样保证。

什么时候草稿值得写

假设目标模型普通一步耗时 10 毫秒。某个推测方案草稿花 3 毫秒、一次批量验证花 12 毫秒,平均确认三个新 token,则示意时间为每 token 5 毫秒;如果平均只确认一个,则变成每 token 15 毫秒。所有数字都是假设值,作用是说明接受率、草稿开销和验证成本必须一起看。

精确推测采样在数学条件与实现正确时保持目标分布,并不承诺每次随机种子下得到逐 token 完全相同的文本;硬件数值也会造成差异。它与量化不同,量化通常改变目标模型的数值与分布,而推测解码改变生成执行方式。两者可以组合,但质量对照基准应说清是原始目标模型,还是已量化的目标模型。

把两个实验分开,才能解释结果

先固定模型与服务配置,只切换量化方案,比较任务成功率、峰值内存、TTFT、TPOT 与吞吐。再固定目标模型,只切换推测方案,记录草稿开销、接受率、平均每次验证确认的 token 数和端到端延迟。最后才测试组合效果,防止一个方案的收益掩盖另一个的退化。

推测解码在低并发、decode 占主导且候选吻合度高时可能有吸引力;高负载时额外草稿工作也会争用资源。常见误区是只看接受率,忽略为了高接受率使用了过于昂贵的草稿;或只比较输出 tokens/s,忽略输出长度和质量已经改变。真正需要优化的是满足质量要求的任务完成速度与成本。

LEARN BY DOING

选择一种优化,并写明它可能失效的条件

  1. 运行量化实验,比较四位、八位及添加大值后的重建误差。
  2. 用手算或表格列出平均确认 token 数为 1、2、3 时的推测方案耗时。
  3. 为真实任务定义质量底线与延迟指标,设计一次只切换一个配置的对照。
  4. 写出量化与推测解码的适用条件、额外开销和失败回退方式。

验收标准

  • 能够区分权重、激活和 KV 三种量化对象。
  • 理论七十亿参数四位纯权重容量为 3.5 GB,没有把它标为实际显存。
  • 解释了为什么平均只确认一个 token 时,示例推测方案反而慢于基线。
下载配套离线实验包 ↓ · 脚本使用模拟模型与数据,运行无需 API。

合上书,检查一下

先作答,再看解释。答错的地方,正好是值得再读一遍的地方。

1. W4A16 可以直接推出什么?
2. 经典精确推测采样为什么不能只按目标概率最高的候选随意接受?

配合本章看视频

下面按本站章节主题选配。为什么没有采用原课录播 →

继续读原始资料

完成状态与自测成绩独立记录。