4.3 Weight-only INT4:GPTQ、AWQ 与 Marlin
理解 GPTQ 的误差补偿、AWQ 的激活感知缩放,以及 Marlin 如何把 INT4 存储转化为推理收益
上一节介绍了平滑变换后再进行 INT8 W8A8 量化的流程。这一节采用另一种配置:权重使用 INT4,激活保留 FP16/BF16,即 W4A16。 4-bit 最多只有 16 种编码,相同覆盖范围下的量化步长会明显增大,对权重误差的处理更重要。GPTQ 和 AWQ 分别从误差补偿与缩放入手,Marlin 则负责高效读取和执行量化后的权重。
📑 目录
- 1. W4A16 的存储和计算
- 2. GPTQ:逐步量化与误差补偿
- 3. AWQ:用激活找出敏感通道
- 4. Marlin:把解包和计算衔接起来
- 5. 怎样比较 GPTQ 与 AWQ
- 总结
- 自我检验清单
- 参考资料
1. W4A16 的存储和计算
INT4 权重通常以打包形式保存在显存中,例如一个 32-bit 容器放 8 个 4-bit 编码,另外保存每组 Scale 和可能的零点。推理时,Kernel 读取这些编码,恢复参与乘法的近似权重。
常见的 W4A16 路径会在计算前把一个小 Tile 的 INT4 权重反量化到 FP16/BF16,再与 16-bit 激活做矩阵乘法。因此,看见“INT4 模型”时,要区分权重的存储类型与乘法指令的输入类型。后面介绍的原始 Marlin FP16×INT4 Kernel 就属于这类路径。Marlin 官方实现
权重虽然在计算前反量化,存储时仍是 4-bit,因此这条路径继续称为 W4A16。分组参数也占空间:若每 128 个 INT4 权重共用一个 FP16 Scale,单看数据与 Scale,平均每个权重是:
还存在零点或对齐开销时,需要继续计入。它最直接的收益是少读权重。至于能省多少时间,要看解包与反量化能否被融合,以及算力、KV 读取和其他算子还占多少比例。
2. GPTQ:逐步量化与误差补偿
2.1 优化目标为什么要带上输入
继续使用 。如果只最小化 ,所有权重误差都按同样的方式计分。但经过线性层后,输入会放大某些误差,也可能让不同通道的误差部分抵消。
GPTQ 使用校准输入,把目标写成层输出的重建误差:
取一个输出通道,其权重为列向量 ,记 ,则:
这个 Hessian 描述了误差在校准输入下的代价,以及输入通道间的相关性。它来自局部线性层的重建目标,无需计算整个语言模型训练损失的完整 Hessian。GPTQ 论文
2.2 为什么补偿有用
先看一个两维例子。若校准输入中的两列近似相同,输出主要取决于 。假设当前量化参数让 对应的重建值为 0.30,相当于多了 0.04;在 还没有量化时,让它减少约 0.04,就可能抵消这次变化。输入列并不相同时,需要根据相关性决定补多少,不能固定“一加一减”。
graph TD
A["浮点权重与校准激活"] --> G1["GPTQ:构造二阶信息"]
G1 --> G2["逐步确定编码,补偿尚未量化的权重"]
G2 --> G3["重复量化与补偿,完成该层权重重建"]
A --> W1["AWQ:统计激活,搜索通道缩放"]
W1 --> W2["应用缩放与裁剪,量化变换后的权重"]
G3 --> E["按目标格式打包权重,导出 Scale 等参数"]
W2 --> E
图中两条路径都使用校准激活。GPTQ 在逐步确定量化值时补偿误差;AWQ 先搜索有利于权重量化的变换,再执行量化。两条路径最后都需要导出符合推理后端要求的检查点。
更具体地,设 是当前尚未固定的权重索引, 是这一子问题的 Hessian。将 固定为量化后的重建值 后,二阶补偿可写为:
其中第 项恰好把 改为 ,其他项给出剩余权重的调整方向。 与原权重处于同一数值尺度,不能直接替换成未反量化的整数编码。实现中还会加入阻尼保证数值稳定,并通过分块更新、Cholesky 分解等方式降低成本。以上公式只说明补偿机制。官方代码
这里的更新块决定一次处理多少权重、何时批量传播误差;量化 Group Size 决定多少权重共享 Scale。两者控制不同的行为,即使数值都设为 128,也不表示它们是同一个参数。
📌 关键点:GPTQ 在离线量化阶段付出更多计算,目标是得到更好的低比特权重。推理时不需要重新估计 Hessian。
3. AWQ:用激活找出敏感通道
3.1 权重大,不一定对输出影响最大
对于 ,某个权重的误差对输出产生 的扰动。若同一个通道经常出现大激活,该通道的权重量化误差就更值得关注。AWQ 因此通过激活统计寻找敏感通道,而不只按权重绝对值排序。AWQ 论文
为了保护这些通道,可以在量化前放大对应权重,同时反向缩小输入。沿用上一节的符号:
这里 生成低比特编码, 用相应 Scale 和零点恢复近似值;公式用 表示参与误差分析的重建权重。若放大某个通道后,所在组的整体量化步长没有同比增大,那么除回 后,该通道的有效误差就可能减小。但放大过度也会拉宽同组范围,损伤其他权重,因此需要搜索合适的缩放,并结合裁剪等策略控制总体误差。
3.2 与 SmoothQuant 的联系
两者都能写成配对缩放,优化目标各有侧重:
| 方法 | 重点处理什么 | 典型配置 |
|---|---|---|
| SmoothQuant | 激活离群值使 INT8 激活难以量化 | INT8 W8A8 |
| AWQ | 少量敏感通道的权重误差被激活放大 | INT4 W4A16 |
AWQ 的激活仍保留 16-bit,因此可以把更多注意力放在权重量化误差上。它的“保护重要权重”主要通过缩放实现,常见部署结果仍是规则的低比特权重布局,不需要把所有重要权重单独存成 FP16。AWQ 官方实现
只执行 AWQ 的缩放搜索,同样得不到打包后的 INT4 模型。比较方法时,要区分“平滑/搜索的中间结果”“模拟量化后的浮点权重”和“已经编码、打包的部署权重”。SmoothQuant、AWQ 的局部变换与各自完整量化流程应分别理解。
4. Marlin:把解包和计算衔接起来
量化权重准备好了,接下来还有一道工程题:怎样让 GPU 读得少,同时不被解包拖慢?
一个低效实现会先把整层 INT4 权重展开成 FP16,写回显存,再启动普通 GEMM。这样既增加临时空间,又多了一次大规模写入和读取,很容易吃掉压缩收益。
Marlin 将权重加载、解包、反量化和矩阵乘法紧密衔接。可以把运行过程理解为:
graph TD
A["HBM 中的 INT4 打包权重 + Scale"] --> B["分块读取,在片上解包与反量化"]
B --> C["与 FP16 激活执行 Tensor Core 矩阵乘法"]
C --> D["累加并写回输出"]
E["预取后续 Tile"] -. "与当前计算重叠" .-> C
预先重排权重,让运行时的读取和指令布局相适配;再用流水线尽量重叠数据搬运和计算。模块二已经讲过 Tiling 与双缓冲,这里增加的工作就是在这些阶段中安排 INT4 解包与缩放。
GPTQ/AWQ 决定怎样得到低误差的编码,Marlin 决定兼容的编码怎样高效执行。 后续推理框架里的 Marlin 实现支持范围可能更广,要根据具体版本检查位宽、Group Size、零点、排列方式和设备支持,不能只凭模型名字判断路径。
5. 怎样比较 GPTQ 与 AWQ
先把算法与部署配置分开。例如,“GPTQ、INT4 W4A16、Group Size 128、Marlin”中的几项信息可以同时成立:
| 配置维度 | 例子 | 说明什么 |
|---|---|---|
| 量化算法 | GPTQ 或 AWQ | 怎样选择变换或补偿,控制量化误差 |
| 格式与位宽 | INT4 W4A16 | 权重采用 4-bit 整数编码,激活保留 16-bit |
| 量化粒度 | Group Size 128 | 每组 128 个权重共享量化参数 |
| 执行实现 | Marlin | 兼容的编码怎样加载并参与计算 |
GPTQ 和 AWQ 都属于前文的 PTQ 路线。W4A16 没有指定使用哪一种算法,相同算法也可能采用不同分组和执行实现。在这些条件明确后,再比较两种方法:
| 维度 | GPTQ | AWQ |
|---|---|---|
| 校准数据的用途 | 构造局部重建目标和二阶信息 | 统计激活,搜索缩放等参数 |
| 主要手段 | 逐步量化并补偿剩余权重 | 改善敏感通道的量化误差 |
| 精度判断 | 看目标模型、校准集与评测结果 | 同样需要目标任务验证 |
| 推理速度 | 取决于导出布局与实际 Kernel | 同样取决于导出布局与实际 Kernel |
因此,“AWQ 一定更快”或“GPTQ 一定更准”都缺少条件。公平对比至少要固定基础模型、位宽、Group Size、输入长度和负载,并记录实际加载的 Kernel。某个方案因布局兼容而选中了更快的后端,另一方案走了普通路径,这体现的是整套部署配置的差异。
排查时可以按下面的顺序推进:
- 确认检查点:量化配置是否完整,基础模型与版本是否相同。
- 看加载日志:是否发生重排,最终使用什么 Kernel,有没有回退。
- 先验质量:避免只挑几条好看的输出,至少准备独立任务集。
- 再测性能:分别观察小 Batch Decode、大 Batch 和长 Prompt;量化省出的空间也可能用于扩大并发。
📝 总结
- Weight-only INT4 压缩权重,激活保持高精度;存储类型与计算类型需要分别看。
- GPTQ 根据校准输入衡量层输出误差,并利用二阶信息补偿尚未量化的权重。
- AWQ 利用激活统计选择缩放,让敏感通道得到更合适的量化表示。
- Marlin 的收益来自数据布局和执行流水线,算法名无法单独决定推理速度。
🎯 自我检验清单
- 能解释为什么 比单看权重误差更贴近层输出
- 能用两个相关输入通道说明 GPTQ 的补偿思路
- 能说明 AWQ 与 SmoothQuant 使用配对缩放时的目标差异
- 能解释先把整层 INT4 展开到显存可能带来什么额外成本