ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

透视 AWQ 激活感知量化:从显著权重保护到 GPU 硬件级反量化加速

透视 AWQ 激活感知量化:从显著权重保护到 GPU 硬件级反量化加速

在追求大语言模型端到端推理极限吞吐的道路上,权重量化(Weight-Only Quantization)是最具实用价值的工程路线之一。相较于全量化(W8A8/W4A4)对激活值动态范围的苛刻要求与昂贵的反量化开销,将模型权重压缩至 4-bit(W4A16)能够在保持标准 FP16/BF16 计算精度的同时,将显存访存带宽压力直接削减 75%。

然而,朴素的整型量化(Round-to-Nearest, RTN)在 4-bit 深度下会引发灾难性的性能坍塌。AWQ(Activation-aware Weight Quantization,激活感知权重量化)的一项关键发现彻底扭转了这一局面:模型中的权重并非同等重要;仅有不到 1% 的显著权重(Salient Weights)决定了绝大部分推理精度。

更为关键的是,判断哪些权重属于“显著权重”,不能依据权重自身的绝对数值大小,而必须观察它们在实际前向传播中所面临的激活值幅值(Activation Magnitude)。

[校准数据集前向传播 (Calibration Dataset)] │ ▼ [捕获各层输入激活值绝对平均分布: s_X = E(|X|)] │ ▼ [识别显著特征通道 (Salient Channels, 占比 <= 1%)] 若通道激活值极大,该通道所对应的全部权重列被列为核心保护对象 │ ▼ [通道自适应等价缩放搜索 (Per-Channel Equivalent Scaling)] W' = W * diag(s), X' = diag(s)^(-1) * X 在不改变矩阵乘法数学等价性的前提下,平抑激活尖峰 │ ▼ [针对缩放后矩阵执行 4-bit 块级均匀量化 (INT4 Grid)] │ ▼ [GPU 硬件级反量化算子内联融合 (Kernel Fusion in CUDA/CUTLASS)] 在片上寄存器/SRAM 级极速反解为 FP16 并执行 Tensor Core 矩阵乘法

显著权重的识别:激活幅值的决定性地位

在传统的权重剪枝或量化算法中,工程师本能地倾向于根据权重自身的绝对大小 $|W_{ij}|$ 来判定重要性,认为数值接近零的权重可以随意截断。但大量实验表明,依据权重幅值挑选出的关键参数进行保护,其困惑度(PPL)改善微乎其微。

AWQ 指出:权重的实际重要性取决于它在计算中所起到的“特征放大效应”。
设某一层线性变换为 $Y = X W$,其中 $X \in \mathbb{R}^{B \times d_{\text{in}}}$ 为输入激活矩阵,$W \in \mathbb{R}^{d_{\text{in}} \times d_{\text{out}}}$ 为权重矩阵。第 $i$ 个输入通道对应的输出特征为:

$$Y = \sum_{i=1}^{d_{\text{in}}} X_{*, i} W_{i, *}$$

如果输入激活在第 $k$ 个通道上存在异常巨大的数值尖峰(Outliers,例如某些坐标上的激活值比平均值高出数十倍甚至上百倍),那么即便对应的权重分量 $W_{k, *}$ 本身数值很小,微小的量化舍入误差 $\Delta W$ 也会在乘以超大激活值后被成百上千倍地放大,直接摧毁后续所有层的特征表征。

因此,AWQ 将特征重要性度量定义为输入激活通道的绝对平均值:

$$S_X(i) = \frac{1}{N} \sum_{j=1}^N |X_{j, i}|$$

凡是 $S_X(i)$ 处于前 1% 极值区间的通道,其所对应的整行权重向量被严格定义为“显著权重集合”。

数学等价变换与通道自适应缩放

如果直接将这 1% 的显著权重保留为全精度 FP16,而在其余 99% 的权重上应用 4-bit 量化(即混合精度存储),在工程落地上会引发巨大的灾难:非规则的稀疏存储格式会彻底打乱 GPU 的内存对齐访问,硬件反量化算子被迫在分支判断中反复横跳,实际推理延迟不仅没有降低,反而比未量化时更慢。

AWQ 提出了一种极其优雅的**数学等价缩放(Equivalent Transformation)**方案:
引入一个对角缩放矩阵 $S = \text{diag}(s_1, s_2, \dots, s_{d_{\text{in}}})$,将矩阵乘法改写为:

$$Y = X W = (X S^{-1}) (S W)$$

我们令新权重为 $\widetilde{W} = S W$,新激活为 $\widetilde{X} = X S^{-1}$。
对于显著通道 $k$,我们选取一个大于 1 的缩放系数 $s_k > 1$。乘以 $s_k$ 后,原本微小的权重被等比例放大;在后续将其映射到离散的 4-bit 整型网格(如 16 个刻度)时,其相对量化舍入误差被成倍压缩!

通过在校准集上最小化输出重构误差:

$$\mathcal{L}(s) = | W X - \text{Quant}(W \cdot \text{diag}(s)) \cdot \text{diag}(s)^{-1} X |_F^2$$

AWQ 采用网格搜索(Grid Search)在极短时间内为每个输入通道寻找最佳缩放比例 $s$。缩放完成后,所有权重矩阵可以以完全规整的结构全量打入 4-bit,无需保留任何零碎的稀疏浮点异常值。

import torch class AWQChannelScaler: def __init__(self, num_grid_steps: int = 20): self.num_grid_steps = num_grid_steps @torch.no_grad() def search_best_scale(self, weight: torch.Tensor, activation_samples: torch.Tensor) -> torch.Tensor: """ weight: [d_out, d_in] activation_samples: [batch_tokens, d_in] 返回值: 维度为 [d_in] 的最佳通道缩放因子 """ d_out, d_in = weight.shape # 1. 计算每个输入通道的激活绝对平均值 act_mean = activation_samples.abs().mean(dim=0) # [d_in] # 计算权重矩阵各通道的绝对平均值 weight_mean = weight.abs().mean(dim=0) # [d_in] # 2. 构造候选缩放网格: s = act_mean^p / weight_mean^(1-p) best_error = float("inf") best_scales = torch.ones(d_in, device=weight.device) # 原始未量化的输出参考 org_out = torch.matmul(activation_samples, weight.t()) for p in torch.linspace(0.0, 1.0, self.num_grid_steps): # 探索不同指数幂比下的平衡缩放 scales = (act_mean.pow(p) / (weight_mean.pow(1.0 - p) + 1e-6)).clamp(min=1e-4) scales = scales / torch.sqrt(scales.max() * scales.min()) # 归一化缩放动态范围 # 应用缩放并模拟 4-bit 块级量化 (此处示意均匀量化) w_scaled = weight * scales.view(1, -1) # 块级最大最小值截断与量化模拟 q_step = (w_scaled.max(dim=-1, keepdim=True)[0] - w_scaled.min(dim=-1, keepdim=True)[0]) / 15.0 w_quant = torch.round(w_scaled / (q_step + 1e-6)) * q_step # 逆向恢复 w_dequant = w_quant / scales.view(1, -1) # 计算重构均方误差 cur_out = torch.matmul(activation_samples, w_dequant.t()) error = (org_out - cur_out).pow(2).mean().item() if error < best_error: best_error = error best_scales = scales return best_scales

GPU 硬件级反量化算子内联融合

将模型权重量化为 4-bit 后,物理存储由每参数 2 字节降至 0.5 字节(两个 4-bit 权重无缝打包至一个 uint8 字节中)。但在实际执行矩阵乘法时,现代 GPU 的 Tensor Core 仍主要支持 FP16 或 BF16 的浮点乘加指令。

若在调用矩阵乘法之前,先启动一个独立的 CUDA 核心把整张权重张量反量化为 FP16 写入显存,就会彻底摧毁量化带来的显存节约与带宽加速。

真正的工业级 AWQ 部署方案(如在 TensorRT-LLM 或 vLLM 中采用 CUTLASS 编写的融合算子)采用的是计算核内部即时反量化(On-the-Fly Dequantization):

  1. 线程块(Thread Block)直接以 uint8 向量化指令(如LDG.E.128)将紧凑的 4-bit 权重从全局显存搬运至片上极速共享内存(SRAM);
  2. 在寄存器级利用位运算指令(如 Fast Bit-Shift 与 AND 掩码)拆包出低 4 位与高 4 位整数;
  3. 利用硬件级浮点转换指令(I2F)并乘上预载入的 FP16 块级缩放因子与偏置,原位恢复为标准浮点数;
  4. 立即调用 WMMA(Warp Matrix Multiply and Accumulate)指令送入 Tensor Core 执行乘加流水。

通过这种“硬件无感、数学保真、算子融合”的极致工程架构,AWQ 成功将 70B 级别大模型的显存占用从 140GB 强力压缩至 38GB 左右,并在吞吐上实现了相对原生 FP16 近 3 倍的吞吐暴增,成为现代高性能大模型推理架构中不可动摇的核心支柱。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进