跳到主要内容

面试题:模型量化怎么省显存?GPTQ、AWQ、GGUF 有什么区别、精度掉多少?

· 阅读需 9 分钟

这是「每日一题」专栏的第十篇。每天一道面试题,后端 + AI 混合路线,从原理到代码一次讲清。上一篇讲了 秒杀系统,今天按轮换回到 AI/LLM 方向,聊上一篇预告的题:模型量化。

题目​

大模型推理面试里和 KV Cache 并列的高频题:

GPTQ、AWQ、GGUF 都是量化,它们到底有什么区别?INT8 和 INT4 各能省多少显存、精度掉多少?什么时候该用哪种?

这道题考察三件事:懂不懂量化的数学本质、会不会算显存和精度账、知不知道主流方案各自的设计动机。很多人能背出「GPTQ 是量化、GGUF 是格式」,但一被追问「AWQ 为什么比 GPTQ 快还更稳」就卡壳。

先给结论,再拆开讲。

方案类型核心思路精度控制手段
GPTQ量化算法(PTQ)逐层逐列量化,用 Hessian 二阶信息补偿误差误差补偿 + 校准集
AWQ量化算法(PTQ)按激活分布找重要权重通道,缩放保护通道级缩放,不需二阶矩阵
GGUF文件格式(不是算法)打包权重和元数据,内置 k-quants 混合位宽不同张量用不同位宽

一、量化到底在做什么​

先讲数学本质。FP16 每个权重占 2 字节(16 bit),INT4 每个占 0.5 字节(4 bit)——把权重从 16 个 bit 压到 4 到 8 个 bit,显存和带宽立刻省一半到四分之三。这就是量化最直接的收益。

但「省」不是白来的:bit 少了,能表示的数值就少了。INT4 只有 16 个取值,怎么把 FP16 的权重塞进去?靠缩放和取整:

q = round(w / s) + z

w = 原始权重(FP16)
s = scale,缩放因子
z = zero point,零点偏移
q = 量化后的整数

反量化就是逆运算:w ≈ (q - z) × s。误差来自 round() 这一步——量化本质是有损压缩,所有方案比拼的都是「同样位宽下,怎么让这个损失最小」。

量化对象有三种:

量化对象量化谁收益风险
权重量化模型权重 W省显存、省带宽,最安全低
激活量化前向传播的中间激活省计算(INT8 矩阵乘用 Tensor Core)高,激活分布动态变化
KV Cache 量化注意力缓存的 K/V省长上下文显存中

面试时先分清这个维度,再说具体方案,立刻显得你懂行。

量化粒度也很关键:per-tensor(整个矩阵一个 scale)、per-channel(每行一个 scale)、group(比如每 128 个权重一组一个 scale)。粒度越细,误差越小,但 scale 的存储开销和计算开销越大。现代方案基本都做到 group 级别,group size 128 是主流默认值。

二、GPTQ:用二阶信息给量化「找补」​

GPTQ 出身学术路线,是 Optimal Brain Quantization(OBQ)的加速版,OBQ 又源于 Optimal Brain Surgeon(OBS)——用**损失函数的 Hessian 矩阵(二阶导数)**判断「砍掉哪个权重损失最小」的老思路。

直觉是这样的:量化一个权重必然引入误差,但误差不是均匀分布的——有些方向的误差影响大,有些方向影响小。GPTQ 逐列量化权重,每量化一列,就用 Hessian 信息算出「这个误差主要会砸在哪些维度上」,然后把这笔误差补偿到对输出影响最小的维度里(数学上就是解一个最小二乘问题)。

原始权重 W → 量化 W_q(引入误差 E)
补偿:把 E 按 Hessian 投影到低影响方向,加到还没量化的权重上
→ 整体输出误差被大幅抵消

几个面试要点:

  • PTQ(训练后量化):不需要重新训练,只需要一小部分校准数据(几百条文本)在模型上跑一遍,记录激活的 Hessian。
  • 逐层处理:一次只处理一个线性层,量化完这一层再下一层,避免误差跨层累积。
  • 为什么适合大模型:校准成本低(几分钟到几十分钟),7B 到 70B 都能跑。
  • 代价:需要 GPU 跑校准,实现复杂(有 Hessian 求逆),对小模型效果一般——模型越小,权重冗余越少,误差越难找补。

三、AWQ:激活说了算,不再看权重本身​

AWQ(Activation-aware Weight Quantization)换了一个视角,来自一个很关键的观察:权重的重要性不是由权重大小决定的,而是由激活大小决定的。同一个权重,如果它对应的激活值一直很大(salient channel),量化它造成的输出误差就大;如果激活值小,误差就小。

于是 AWQ 的思路变成两步:

  1. 找重要通道:在少量校准数据上统计每个通道的激活幅度,找出占比极少(大约 1%)但贡献巨大的 salient channels。
  2. 缩放保护:不直接对这些通道特殊处理(那样实现复杂),而是给每个通道乘一个缩放因子(数学上等价于把量化 scale 放大),让重要通道在量化时吃到的 round 误差相对更小。
原始权重 W → 乘通道缩放 s(保护重要通道)→ 再量化
反量化时除回 s,输出几乎不变

AWQ 相比 GPTQ 的优势,面试里是加分项:

对比维度GPTQAWQ
原理依据权重二阶信息(Hessian)激活分布统计
校准开销需要算 Hessian,较慢只统计激活幅度,快得多
实现复杂度高(矩阵求逆)低(纯缩放)
泛化性对分布偏移敏感对多模态、指令微调模型更稳
代表应用GPTQ 工具链vLLM 内置 AWQ、TensorRT-LLM

一句话记忆:GPTQ 是「权重犯的错,用数学找补」,AWQ 是「先看哪些权重不能动,再保护它们」。

四、GGUF:它根本不是量化算法​

这是最多人搞混的点。GGUF 是 llama.cpp 定义的一种模型文件格式——把权重、tokenizer、超参数、量化参数打包成一个文件,方便 CPU 和边缘设备加载。它不是量化方法,但它内置了一套量化方案叫 k-quants。

k-quants 的精髓是混合位宽:

量化名含义典型用途
Q4_K_M中等 4-bit 混合量化默认选择,性价比最高
Q5_K_M5-bit 混合精度敏感场景
Q8_08-bit,每块一个 scale接近无损
Q2_K2-bit 极限压缩显存极小但质量明显下降

「混合」体现在:重要张量(attention 的 q/k/v 投影、输出层)用更高位宽,不重要的(FFN 中间层)用更低的 bit,块大小也比普通 group 更灵活。所以同样的 4-bit,GGUF 的 Q4_K_M 通常比朴素 INT4 效果好。

GGUF 的意义在于生态:llama.cpp / Ollama 直接跑,没有 GPU 也能推理,量化好的模型文件(比如 HuggingFace 上的 4-bit 版本)开箱即用。

五、算账:显存省多少、精度掉多少​

以 LLaMA-2-7B(70 亿参数)为例:

方案每参数位数权重大小相对 FP16
FP1616 bit约 13 GB1 倍
INT88 bit约 7 GB一半
INT4(group 128)4 bit约 3.5 到 4 GB四分之一
GGUF Q4_K_M混合 4 到 6 bit约 4 GB约三分之一

精度上,业界公认的经验值(以困惑度/Wikitext 为例):

  • INT8:几乎无损,困惑度上升约 0.1,绝大多数场景无感。
  • INT4(group size 128):困惑度上升约 0.3 到 0.5,日常对话几乎无感,代码、数学等敏感任务能感觉到轻微退化。
  • INT4(group size 32):粒度更细,困惑度上升可压到 0.2 以内,但推理变慢(scale 计算开销大)。
  • Q2/Q3:困惑度上升超过 1,一般只用于显存实在放不下的场景。

两个容易被追问的点:

为什么 4-bit 掉精度没想象中严重? 因为量化误差是「随机噪声」性质的,模型输出的概率分布被扰动一点,argmax 出来的 token 往往不变;而且现代模型(尤其是大模型)有大量冗余参数,对权重扰动天然鲁棒。模型越大,量化越「耐造」。

KV Cache 量化呢? 上一篇讲过 KV Cache 占显存大头,所以现在推理引擎普遍支持把 KV Cache 量化到 INT8(几乎无损)甚至 INT4(长上下文场景收益巨大),和权重量化叠加使用。

六、面试回答模板​

按这个顺序答,逻辑闭环:

  1. 先给本质:量化是用更少的 bit 表示权重,靠 scale + round 实现,是有损压缩,所有方案都在比「怎么少掉精度」。
  2. 再给方案:GPTQ 用 Hessian 二阶信息做误差补偿;AWQ 按激活分布保护重要通道;GGUF 是文件格式加 k-quants 混合位宽。
  3. 最后给选型:
场景推荐
服务端高吞吐推理(vLLM/TensorRT)AWQ 或 GPTQ INT4,配 KV Cache INT8
CPU / 边缘 / 本地跑GGUF Q4_K_M(llama.cpp/Ollama)
精度敏感(代码生成、数学)INT8 或 Q5/Q6,别上 Q2
显存极度紧张INT4 加 KV Cache INT4,接受精度轻微下降

收尾金句:量化不是「精度换显存」的单选题,而是「用最少的精度代价换最多的显存收益」的工程题——选型的本质,是搞清楚你的模型哪些权重碰不得。


明日预告:后端/分布式方向 ——「先更新数据库还是先删缓存?Cache-Aside 到底哪里会出错、怎么保证最终一致?」