一、压缩到底在省什么:先把三笔账分开
几乎每篇讲压缩的文章都会从“参数减半、显存减半”开始,然后得出“速度翻倍”的结论。这个推理链里藏着两个独立的跳跃:压缩首先省的是存储和搬运,而不是计算;而“省了搬运”只有在模型处于显存带宽受限状态时才转化成延迟收益。把这两件事分开,才能解释为什么一个 4bit 权重模型在单请求短上下文下可能比 BF16 还慢,而在一个 64 并发长上下文服务里快得多。
所以先做一次概念清理。推理一个 Transformer 的成本,至少可以拆成四个作用面:
- 权重显存:模型参数本身要占多少 DRAM。这是最容易测、也最常被当成全部的故事。
- KV Cache 显存:随序列长度线性增长的那一块。它和并发数、上下文长度、以及 GQA 配置耦合得比权重更紧。
- 显存带宽:每生成一个 token,要从 DRAM 里读多少字节。权重访存是刚性的,KV 访存是随长度增长的。
- 算力(FLOPs):真正做乘加的次数。权重量化几乎不改变它,激活量化才会。
这四个作用面对不同手段的响应完全不同,把它们排成一张表,很多看似矛盾的社区结论就解释得通了。
| 手段 | 权重显存 | KV 显存 | 访存带宽 | 算力 | 成本转移到了哪里 |
|---|---|---|---|---|---|
| 权重量化(weight-only) | 强(4~8×) | 无 | 强 | 基本不变,甚至略增 | 转移到端侧部署门槛与精度风险 |
| 激活量化(W8A8 / W4A8) | 中 | 无 | 中 | 强(依赖低比特张量核) | 转移到硬件支持与 kernel 覆盖度 |
| KV Cache 量化 | 无 | 强(2~4×) | 随长度线性变强 | 无 | 转移到长上下文质量与首 token 之后的稳定性 |
| 非结构化 / 2:4 剪枝 | 强(2×) | 无 | 取决于能否命中稀疏核 | 取决于稀疏核 | 转移到训练或恢复训练与硬件型号 |
| 结构化剪枝 | 中(按剪枝比例) | 可能顺带减少 | 强 | 强 | 转移到需要重新训练补能力 |
| 蒸馏 | 强(取决于学生规模) | 随学生一起降 | 强 | 强 | 全部转移到数据构造与教师调用成本 |
| 激活稀疏 / 动态稀疏 | 中 | 无 | 中 | 强 | 转移到推理 kernel 与动态形状开销 |
从表里能直接读出三个结论。第一,权重量化不碰 KV Cache,很多人在做 128K 长上下文服务时把显存爆掉仍然去调权重量化位宽,这是找错了对象。第二,只有激活量化和结构化剪枝真正减少 FLOPs,而这两者恰好是对精度最敏感的两种操作。第三,蒸馏是唯一四种全中的手段,代价却是它需要一次完整的训练,这是它和其他手段不在同一个成本维度上的根本原因。
1.1 判定你的推理瓶颈在带宽还是在算力
在动手选任何压缩方法之前,有一件事必须先测出来:你的服务是 memory-bandwidth-bound 还是 compute-bound。粗略的判据是看算术强度——每生成一个 token 需要读的字节数,与实际完成的 FLOPs 的比值。对于一个稠密自回归 Transformer,权重是每步都要完整读一遍的,而每一步只做权重参数量次乘加,所以权重这一段的算术强度大致是一个小于 1 的常数,它不随 batch 变化。这直接导致一个反直觉但极其重要的现象:
- 单请求、小 batch:GPU 算力有大量闲置,绝大部分时间在等 DRAM 喂数据。此时压缩权重是最高杠杆的操作,收益近似线性地体现在 TTFT 和 TPOT 上。
- 大 batch、长上下文:当 batch 大到让矩阵乘的 FLOPs 把带宽填满,模型转为算力受限。此时再压权重,收益迅速衰减;而此时真正拖慢你的是 KV Cache 的读写和 attention 计算本身。
这就是为什么“同一个模型,量化后单机快了 1.6 倍,压到 32 并发只快了 1.1 倍”这类反馈到处都是。它不是量化方法有问题,而是压缩手段作用在了一个不再受限的维度上。工程上最实用的做法是:先用请求日志里的平均输入长度、平均输出长度、并发数和生成长度分布,算出每一步的权重读取量和 KV 读取量,再决定先动哪一头。
压缩的收益曲线不是一条线,是一条以“瓶颈在哪里”为横轴的分段函数。先定位瓶颈,再选方法,顺序反了会浪费掉一整轮实验预算。
二、权重量化:位宽、分组与异常值这三件事必须一起想
权重量化是把每个权重从 16 位浮点映射成一个低比特整数加一组量化参数。形式上极简,但“好不好”完全由三个正交的选择决定:目标位宽、量化参数放在多大的粒度上、以及如何处理离群值。很多人只调第一个,然后抱怨效果不稳定。
2.1 位宽的收益是次线性的,而且元数据会吃掉一部分
朴素的心算会告诉你 INT4 是 INT8 的两倍好、BF16 的四倍好。实际不是,原因有两个。
第一,低比特的动态范围塌缩得很快。INT8 大约提供 7 位有效尾数,INT4 只有 3 位;当一个张量里绝大多数权重的绝对值集中在很小的一段区间时,均匀量化的步长会变得很粗,靠近零的那批小权重会被整批映射到同一个码字上,彻底丢失信息。这就是为什么从 8bit 降到 4bit 的质量损失,通常远大于从 16bit 降到 8bit 的损失,而且损失曲线在 3~4bit 附近有一个明显的拐点。
第二,缩放参数本身要占字节。以最常见的 group-wise 对称 INT4 为例,假设 group size 取 128,每组存一个 FP16 的 scale(16 位)加一个 4bit 的零点(打包后 4 位),额外开销是 20/128 ≈ 0.156 bit/权重。也就是说名义 4bit 的方案,真实落盘是 4.16 bit/权重。用同样方式算:一个 7B 模型 BF16 权重约 14 GB,纯 INT4 理论值 3.5 GB,加上分组元数据约 3.64 GB;一个 70B 模型 BF16 约 140 GB,INT4 加元数据约 36 GB。group size 从 128 降到 64,元数据开销翻倍到约 0.31 bit/权重,压缩比从 3.85× 掉到 3.72×——这个差别不大,但量化参数在张量里的复用次数减半,效果提升通常是能感知到的。group size 32 再往下降,开销逼近 0.63 bit/权重,压缩比掉到 3.46×,而收益开始递减,缓存中的 scale 数组还会反过来挤占内存带宽。
| 位宽 | 有效精度 | 典型格式 | 7B 权重体积(含元数据) | 适用判断 |
|---|---|---|---|---|
| BF16 / FP16 | 训练原格式 | bf16 | 约 14 GB | 有充足显存、或需要做数值对照时 |
| FP8 | 约 3~4 位尾数 | E4M3 / E5M2,可带 per-tensor 或 per-block scale | 约 7 GB | 几乎免费的一档,常作为训练侧与推理侧的默认中间格式 |
| INT8 | 7 位有效 | 对称/非对称 per-channel,per-token 动态 scale | 约 7 GB + scale | 通用性最好,成熟硬件支持;质量损失通常可忽略 |
| INT6 / FP6 | — | 常以 per-group scale 的浮点或整型表示 | 约 5.6 GB | 想比 INT4 稳、又比 INT8 小的折中档,常是性价比拐点 |
| INT4 / FP4 | 3 位有效 | per-group 整型;或块缩放浮点(每 16 或 32 个元素共享一个 scale) | 约 3.6~3.9 GB | 消费级单卡、边缘部署的主流档;必须配分组或块缩放 |
| INT3 / INT2 | ≤ 2 位有效 | — | 约 2.7 / 1.8 GB | 几乎只对极窄场景有意义,通用任务上质量塌陷 |
还有一条容易被忽略的账:元数据和 kernel 常驻。如果实现是逐组反量化,scale 数组、量化参数缓冲区、可能还有未融合的算子工作区,都要占显存。在 4bit 方案上,这些“非权重开销”可能占到总显存的 5% 到 15%,不测算就会高估压缩比。
2.2 分组:把预算花在最需要的地方
量化的核心矛盾是“步长”和“分辨率”的取舍。一个 scale 覆盖的元素越多,参数越省,但同一个 scale 下的权重差异被抹平得越厉害。粒度从粗到细排列如下:
- per-tensor:整个权重张量一个 scale。元数据几乎为零,质量最差,只在权重分布极度均匀的层或极保守的场景用。
- per-channel(per-output-channel):每个输出滤波器一个 scale。开销约为 1/group 的零头,几乎免费,是所有现代 PTQ 方法的默认起点,因为它对应的是权重在输出维度上的天然结构。
- per-group:在一维上切 64 或 128 的组再各自一个 scale。质量提升最明显的一档,也是 4bit 方案的事实标准。
- per-group + 零点(非对称):额外给每组一个零点。当权重分布明显右偏(大量小正数)时收益明显,开销约 0.03~0.06 bit/权重。
一个实践上很有用的判断:group size 是“元数据开销”和“量化分辨率”之间唯一可调的旋钮,而位宽是“显存”和“质量”之间唯一可调的旋钮。工程上应该先把位宽定在你必须满足的显存线上,再在这个线上把 group size 从 128 调到 64 看质量是否够用——这个顺序比反过来试要快得多,因为位宽一旦降下去,group size 调小也救不回来。
2.3 离群值:LLM 权重里那几个不听话的通道
Transformer 权重和激活的分布有一个众所周知的病理特征:绝大多数元素挤在 0 附近,但少数通道存在幅度远超其他通道的系统性离群值(outlier channel)。这不是噪声,是训练收敛的结果。
这个特征对量化是双重打击。对权重:一个离群值会把所在 group 的 scale 撑大,导致同组内所有正常权重被压缩到少数几个码字附近,等效于这些权重被清零。对激活:离群通道会在每一层都把 scale 撑大,迫使整层用低精度表达,而实际信息量并没有那么大。
针对权重侧,主流的处理有两类。第一类是裁剪离群值:在量化前把超出某分位数的权重截断,宁可牺牲少数单元也要保住整体的分辨率,它便宜但粗暴。第二类更精巧:把离群信息拆出去单独存,主体部分低比特量化,少数离群值保留更高精度或直接存成稀疏例外表,再在反量化时加回去。第三类、也是 2025 年以来影响最大的一类,是把离群值“旋转”掉——用一个正交变换把权重和激活同时变换到一个更均匀的坐标系里,让离群通道在数学上消失,量化完再把旋转折进相邻算子。这个思路的推广形式(把随机正交变换、Householder 变换、在线 Hadamard 变换都算作同一族)已经成了 2025—2026 年 PTQ 的标准前处理步骤之一,尤其在 W4A8 场景里几乎是必需的,因为它的主要战场就是激活量化。
判断你的模型是否被离群值主导,有一个廉价实验:分别做一次纯 per-tensor 量化和一次 per-channel 量化,如果两者的困惑度差距远大于直觉,那说明该层存在显著的离群通道,优先上旋转类前处理而不是继续缩位宽。
2.4 浮点位宽与块缩放:2025—2026 真正在动的方向
整数低位宽的动态范围问题,本质上被“块缩放(block scaling)”解决了:把权重切成很小的块,每块共享一个浮点 scale,块越小、scale 越贴合局部范围,有效精度就越高,而 scale 的开销被摊薄到很小。MX 规范把这个思路标准化了——32 个元素共享一个 E8M0 功率次方的 scale。NVIDIA 的 NVFP4 走了另一条路:每 16 个元素一个 FP8 的 E4M3 scale,加上一个全局的 FP32 per-tensor scale,用来表达块与块之间的尺度差异。
这两个格式的意义不只是“又多了两个格式名”,而是把4bit 从一个需要 group-wise 整数技巧才能用的档位,变成了一个浮点语义下的原生档位。代价是元数据开销上升:NVFP4 每 16 元素一个 FP8 scale,开销是 8/16 = 0.5 bit/权重,名义 4bit 实际 4.5 bit;MXFP4 每 32 元素一个 8 位 scale,开销 0.25 bit/权重,实际 4.25 bit。对一个 7B 模型,4.5 bit 意味着约 3.94 GB 而不是 3.64 GB——多出来的 300 MB 换来的是不再需要非对称零点、分布偏移容忍度更好。是否划算,取决于你的目标硬件有没有对应的低比特浮点张量核。
同一时期另一个明确趋势是 FP8 从推理侧彻底进入了训练侧。用 FP8 做前向和反向的混合精度训练,配合细粒度的分块累加,已经足以支撑大规模 MoE 模型的训练,而不再只是推理时的权重量化选项。这带来的一个副作用常被忽视:模型是用 FP8 训练出来的,它的权重分布天生就更适配 FP8 推理,量化到 FP8 时几乎无损,而量化到 INT4 时的表现则不一定比其他模型更好。这意味着“压缩方案的收益”部分地由训练格式决定,换模型时不能沿用上一家的量化经验。
还要提一句精度选择本身的语义:E4M3 尾数多、动态范围小,适合数值敏感的前向激活;E5M2 尾数少、动态范围大,通常给梯度或对范围更敏感的量。这个分工和 BF16/FP32 的直觉是反的,配置时容易配错。
2.5 校准集:被忽视但影响最大的一个超参
PTQ 需要一小批数据来估计每一层的激活统计(通常是每通道的绝对值最大值或分位数),这批数据叫校准集。它只有几十到几千条样本,看起来不重要,实际上它对最终质量的影响可以和位宽选择相当。三个必须注意的点:
- 分布要对齐。用通用语料校准、然后部署到代码或中文任务上,激活范围会错配。用目标任务的样本,哪怕只有几百条,效果通常好于用十万条通用语料。
- 要覆盖长度分布。长上下文任务的激活分布随位置变化,短视频校准出来的 scale 在长位置上可能不合适。
- 不要用训练集里的记忆样本。校准虽然不更新权重,但用它做统计会让 scale 过拟合,评测集上的表现会比真实场景更好看。
另一个近年才被系统化处理的问题是 softmax 之后的输出。它天然有一条长尾分布,直接做逐 token 量化会被少数大值支配。逐 token 动态求 max 能解决大部分问题,这也是为什么现代 KV 量化和激活动态量化都默认逐 token 做。
2.6 激活量化:唯一能真正减少算力的那一档
前面几节讨论的全部是权重量化,它把权重变小,但每一步要做的乘加次数一分没少。如果目标是把延迟从算力受限的区间里压出来,激活量化才是那条路:它把矩阵乘的输入和中间结果也压到低精度,从而让乘加真正在低比特张量核上执行。
它的困难程度比权重量化高一个量级,原因有三层。第一层是离群值:权重的分布是静态的,可以在量化之前反复统计和调整,而激活是每一步动态生成的,上下文一变分布就变,任何全局统计都会失配。第二层是误差传播:权重误差只影响本层的输出,而激活误差会通过残差连接渗到后续每一层,深度越深放大越厉害。第三层是 kernel:即使量化参数算得再准,没有对应的融合 kernel,或者 kernel 需要在线计算 scale 并做动态整形,实际速度可能还不如不量化的 BF16 路径。
因此激活量化的现实路径是从 8bit 起步,而不是直接冲 4bit。W8A8 的思路是权重走 8bit 整数、激活走 8bit 且逐 token 动态求 scale,配合通道平滑或旋转把离群通道压下去,这一档在主流加速卡上已经有成熟 kernel,是可以放心使用的生产方案。W4A8 则是另一回事:权重压到 4bit 已经能显著减少访存,激活保持 8bit 主要是为了保住数值精度,同时让矩阵乘仍能命中低比特指令集——这里的收益其实主要还是来自权重访存的减少,激活那 8bit 是为了让这个收益不因精度损失而消失。把激活也压到 4bit(真正的 W4A4)在通用任务上质量塌陷明显,通常只在极窄的、已充分验证的场景里才值得考虑。
| 方案 | 权重 | 激活 | 访存收益 | 算力收益 | 2026 年判断 |
|---|---|---|---|---|---|
| BF16 基线 | 16 bit | 16 bit | 基准 | 基准 | 所有对比的原点 |
| Weight-only INT4 | 4 bit | 16 bit | 约 3.7 倍 | 无 | 最常用,收益集中在带宽受限场景 |
| W8A8 | 8 bit | 8 bit 动态 | 约 2 倍 | 有 | 生产可用,需要前处理去掉离群值 |
| W4A8 | 4 bit | 8 bit 动态 | 约 3.7 倍 | 部分 | 推理侧主流的兼顾形态 |
| W4A4 | 4 bit | 4 bit | 约 3.7 倍 | 有 | 通用任务上不稳,慎用 |
最后一列是选型时最该看的一栏:访存收益的来源和算力收益的来源必须分开计算。一个 W4A8 方案在单请求下拿到的加速,绝大部分来自权重访存从 2 字节变成 0.5 字节;只有当大 batch 把机器推进算力受限区间,激活量化那部分收益才开始显现。把两者混在一起谈,就会得出我上了 W4A8 却没变快的错误结论——而实际情况通常只是服务根本不在算力受限区间。
2.7 一个最小可用的量化自检流程
在进入任何具体方法之前,有一套不需要写很多代码的自检流程,能挡掉绝大多数量化做完效果不好的情况。它的价值在于每一步都很便宜,但每一步都能否定一个方向。
- 先确认权重分布是不是真的均匀。把某一层权重按绝对值排序,看最大的百分之一元素占了总绝对值的多大比例。如果这个比例很高,说明存在强离群,应该优先上旋转或裁剪,而不是先调分组粒度。这个检查用几行代码就能做完,却经常能直接改变选型方向。
- 做一次纯对称、纯逐张量的暴力量化,把质量损失记下来。这是所有分组方案和缩放方案的下界,参考价值极高。如果暴力量化就已经掉得很多,说明问题出在分布本身而不是量化器;如果暴力量化几乎不掉,那后面所有收益都来自分辨率,值得投入。
- 只改一个变量,扫一遍分组粒度。在固定位宽下从小往大扫,看质量曲线在哪里变平。找到那个拐点比沿用默认值可靠得多——默认值是别人的模型上测出来的,不一定适合你的分布。
- 最后才引入误差修正类算法。它应该是在分辨率已经够用的前提下,把最后一点损失捞回来。如果在很粗的分辨率上试图用误差修正来补救,收益会远低于先把分组粒度调小。
这个流程的隐含逻辑是先解决分布问题,再解决分辨率问题,最后才轮到算法技巧。绝大多数人反过来做,先去试各种算法,然后发现真正的瓶颈是一个用二十行代码就能检出的离群值问题。顺序对了之后,能搜的算法空间其实很小,收益却更确定。
三、GPTQ 与 AWQ:同一个问题,互补的两个视角
GPTQ 和 AWQ 常被并列当成“两种 4bit 方法”二选一,但它们其实在回答两个不同层面的问题,而且经常被叠加使用。理解这个区别,比记住哪个更准更有价值。
3.1 GPTQ:把量化误差看成跨列耦合的传播问题
GPTQ 的出发点是一个很多人忽略的事实:逐列量化时,前面列的舍入误差会改变后面列的量化结果。如果各列独立量化,误差是独立累加的;但如果利用权重 Hessian 矩阵的逆把误差重新分摊,理论上可以让最终重建权重的总误差更小。
它的工程化实现依赖一个二阶近似:把量化造成的增量视为对 Hessian 加权目标函数做一步更新,然后在每一列量化完之后用 Cholesky 分解把已产生的误差反向分摊给尚未量化的列。这就是为什么 GPTQ 需要逐列处理、需要维护一个累加误差向量,也为什么它比朴素的 round-to-nearest 慢——它多做了一整轮列间的数值修正。
GPTQ 的三个真实使用要点:
- 它默认作用在 per-channel 或 per-group 之上,不替代分组。4bit 方案几乎都要 group-wise(常见 128),GPTQ 是在这个基础上修正舍入,不是取代它。
- 校准集的小 batch 顺序敏感。同一份数据不同切分可能给出略有不同的结果,评测时要固定并记录种子。
- 它对激活分布不敏感,只用权重 Hessian,所以非常适合 weight-only 场景;但也正因为不建模激活,它在 W4A8 上的收益远不如激活感知方法。
3.2 AWQ:显著通道由激活决定,但要用权重来保护
AWQ 的观察是另一侧的:只有 1% 左右的权重对模型输出影响最大,而且这些显著权重是由输入激活的幅度决定的,不是由权重自身的大小决定的。这是很多人凭直觉会搞反的一点——权重大不代表重要,因为大权重如果总是乘在小激活上,贡献就小。
AWQ 的做法是找一个逐通道的缩放系数 s(作用在输入维度上),把激活中的显著通道放大、把不重要通道压小,从而让重要的那批权重在数值上占据更大的动态范围,量化时更不容易被舍掉。这个缩放是数学等价的变换,推理时可以被吸收进前一层的权重里,不增加任何推理开销。
它和 GPTQ 的互补关系由此清楚:
| 维度 | GPTQ | AWQ |
|---|---|---|
| 优化的目标量 | 权重的重建误差(用 Hessian 加权) | 激活分布的通道显著度 |
| 是否需要激活数据 | 需要,但只用来构造 Hessian | 需要,用于统计通道显著度 |
| 改动位置 | 权重的舍入与误差分摊 | 输入维度的 per-channel 缩放(推理时吸收) |
| 推理额外开销 | 无 | 无(缩放被折进前一层) |
| 与分组的关系 | 配合 per-group 使用 | 配合 per-group 使用 |
| 典型搭配 | 与 AWQ 的缩放先后组合 | 与 GPTQ 的舍入先后组合 |
一个值得记住的工程结论是:这两件事不冲突,工程实现里经常先做通道缩放、再做 GPTQ 式舍入。缩放改善了权重的分布条件,GPTQ 在这个更好的分布上再做误差分摊。生态里常见的“GPTQ + AWQ 风格缩放”组合就是这个意思,而不是两种互斥的算法。
3.3 更完整的工具箱:旋转、平滑与混合精度分解
到 2026 年,只提 GPTQ 和 AWQ 已经不完整。活跃的几个方向构成了现代 PTQ 的补充层:
- 旋转 / 不相干处理(QuaRot、SpinQuant、QuIP# 一族)。用正交变换把权重和激活的离群通道打散到所有通道上,让 per-tensor 量化也能工作。对 W4A8 几乎是必选项,因为它同时解决了激活侧的离群问题。代价是变换本身要付出一次离线计算,以及在线 Hadamard 变换带来的额外 kernel。
- 激活平滑(SmoothQuant 一族)。思路和 AWQ 接近但目标不同:把激活的离群难度迁移到权重侧,因为权重是静态的、量化误差更好控制,而激活是动态的、难处理。缩放同样可以吸收进前一层的权重。
- 混合精度分解(OmniQuant 一族)。把每个线性层写成低比特主体 + 少量高比特/浮点残差,逐层搜索残差的最优秩。这本质上是把量化问题变成了一个低秩分解问题,在 2~3bit 档位上比纯低位宽更有优势。
- 无校准 / 优化式方法(AutoRound 一族)。把每层权重视作可优化变量,用训练式的优化来求更好的舍入点,代价是一次比 GPTQ 重得多的离线过程,通常几十分钟到几小时。
把这层看清之后,一个实用的选择逻辑是:weight-only 4bit 求稳,GPTQ 家族加 per-group 128 足够;要 W4A8 求吞吐,先旋转再量化;卡在 3bit 及以下,混合精度分解比硬啃分组更值得试。
四、KV Cache 量化与 FP8:长上下文真正该动的地方
如果你的场景里权重已经压到 4bit 而显存还是不够,问题几乎一定不在权重上。KV Cache 是长上下文与高并发场景里唯一随序列长度线性增长、且增长系数不受你控制的那块内存,它才是这类部署的主要矛盾。
4.1 先把 KV 的体积算清楚
KV Cache 的字节数有闭式公式:2 × 层数 × KV 头数 × head_dim × 每元素字节数 × token 数。注意这里的头数是 KV 头数而非注意力头数——GQA/MQA 把这部分压小了若干倍,是现代长上下文模型能跑起来的关键之一,压缩方案必须建立在实际的 KV 头数上,不能用注意力头数估算。
举一个纯算术的例子:一个 80 层、8 个 KV 头、head_dim 为 128 的配置,FP16 下每 token 是 2 × 80 × 8 × 128 × 2 = 320 KiB。开满 128K 上下文,单条序列的 KV 就是 40 GiB 量级——这还没算权重、激活工作区和框架开销。换算成不同精度:FP8 约 20 GiB,INT8 约 20 GiB,INT4(group 64 加元数据)约 11 GiB。这组数字说明两件事:长上下文下 KV 常常比权重大一个量级;以及KV 量化的收益是线性叠加的,不需要什么精巧算法,它从 FP16 到 INT4 就是实实在在的四倍。
4.2 为什么 KV 量化比权重量化更容易
直觉上 KV 比权重更难压,因为它是动态生成的、分布随内容变化。之所以实际效果好,有三个原因:
- 它的误差不跨步累积。权重的量化误差会通过每一层的输入传播到后续所有层,层数越深放大越明显;KV 的误差只在当前这一步的注意力计算里起作用,下一步会生成新的 KV,不存在沿着序列长度累积的路径。这是 KV 量化最被低估的优势。
- 软最大本身有容忍度。注意力权重是归一化后的相对量,注意力分数的等比例缩放不改变结果,softmax 对小扰动的一阶导在小值区接近零。这给了量化留了余量。
- 可以逐 token 动态定标。每个 token 自己的 K 和 V 单独求 scale,完全不需要跨 token 共享,粒度天然很细。
代价也真实存在,而且集中在一个地方:注意力分数被量化噪声扰动后,检索排序会出错。在“针在草堆里”这类需要从大量上下文里精确捞出一条信息的任务上,这种错误最先暴露。所以 KV 量化的评测不能只看总体困惑度,一定要包含长上下文检索和长文本推理子集。
4.3 粒度选择:per-token、per-channel 还是 per-head
KV 量化最关键的设计变量是 scale 的粒度,三种主流选择的权衡如下。
| 粒度 | 元数据开销 | 质量 | kernel 复杂度 | 说明 |
|---|---|---|---|---|
| per-tensor / per-layer | 几乎为零 | 最差 | 最低 | 不同序列长度、不同内容之间互相污染,不建议用于生产 |
| per-token(K 和 V 各自) | 很低 | 好 | 低 | 当前的主流默认值;动态计算 scale,无预计算负担 |
| per-head | 低 | 更好 | 中 | 不同注意力头的动态范围差异明显时收益可见 |
| per-channel | 中等 | 好,但有方向性风险 | 高 | 按 K 的 head_dim 归一化会压掉查询侧的通道选择信号,检索类任务可能明显变差 |
这张表里最反直觉、也最重要的一行是 per-channel。直觉上粒度更细一定更好,但按 head_dim 做 channel-wise 缩放有一个副作用:它会改变不同通道对查询点积的相对贡献,而这些通道正是模型用来做“匹配”的。如果缩放对 K 和 Q 不对称,注意力分数的语义就被破坏了。结论是:细粒度不一定更好,per-token 是绝大多数场景的稳妥解;per-channel 只在你验证过检索任务不掉点时才用。
4.4 关键感知与查询感知:选择性量化的思路
另一条思路来自一个观察:不同位置、不同头、不同通道对最终输出的贡献差异极大,没有必要一视同仁地压。
- 关键感知:给每个 token 或每个头估计一个重要性分数,对高重要性部分保较高精度,对其余部分压得更狠。难点是重要性估计本身的可靠性——一个用启发式规则算出来的分数,如果在长文本里判断错误,反而比均匀量化更糟。
- 查询感知:注意到当前解码步骤的查询向量 q 是已知的,于是可以对不同 K 值使用不同的量化参数,让量化误差对当前查询影响最小。这个思路在数学上很自然,但工程上要付出按 q 重新计算的开销,且没有利用 KV 已经缓存好的前提,实现难度大。
这两条思路目前的共同状态是:理论收益清晰,实现收益不稳定,工程复杂度高于 per-token 方案。对绝大多数生产部署,先把 per-token 的 INT8/FP8 跑扎实,收益已经拿到了,再考虑要不要为特定任务上选择性方案。
4.5 FP8 在推理引擎里的真实位置
FP8 在 2025—2026 年已经从“新格式”变成了推理引擎的默认中间精度,但它的位置常被说错。它主要出现在四个地方:
- 权重存储:作为 8bit 的替代方案,在保持同等体积的同时提供更好的动态范围,常见于服务侧的“保底精度”档位。
- 激活与中间结果:attention 的 P×V 中间态、FFN 的中间激活,以及各类归约的累加器,这是收益最大的一处。
- KV Cache:E4M3 存 K 和 V 是当前的稳妥选择——K 参与点积、数值敏感,用尾数多的 E4M3;V 参与加权求和、可以放宽。这一条几乎已经是被广泛采用的默认配置。
- 训练侧:如前所述,FP8 混合精度训练让模型从源头就适配 FP8 推理。
一个必须检查的细节:FP8 的累加精度和舍入模式会显著影响结果。很多实现里 FP8 乘加的累加是在 FP16 或 FP32 做的,但舍入发生在乘法之前还是之后、是否用 split-k 累加、以及有没有对 attention 的 softmax 输入做特殊处理,这些都会造成可观测的差异。跨框架比较 FP8 结果时,先确认累加语义一致,否则差异可能来自实现而不是模型。
长上下文部署的压缩顺序应该是:先确认 GQA/MQA 的 KV 头数,再上 KV 的 FP8/INT8 量化,然后才回头考虑权重量化。把权重从 8bit 压到 4bit 换来的显存,可能还不如把 KV 从 FP16 压到 FP8 的一半多。
4.6 长上下文的另一条路:不是所有问题都该用 KV 量化解决
KV 量化解决的是同样的 KV 用更少的字节存下来,但它没有解决更上游的那个问题:根本不需要这么多 KV。长上下文方向上还有两类互补手段,值得和量化一起放进同一张选型表里比较。
第一类是KV 的选择性与淘汰。已经算出来的 KV 里,绝大多数在后续解码中几乎不会再被用到,典型的是一段长文档里被后续问题完全忽略的那些部分。基于这个观察的做法是:用一个轻量的判据给每个位置打重要性分,只保留高分的部分,其余直接从缓存里移除。关键区别在于它的收益是随序列长度持续增长的,而 KV 量化的收益只是一个常数倍——在几十万 token 的场景里,淘汰能省下的空间远大于压位宽。但风险同样直接:一旦判据把真正需要的位置淘汰掉,模型会给出自信而错误的回答,而且这种错误在常规评测里很难被发现,因为它不体现为总体分数的明显下降,只体现为个别难题答错。这也是为什么淘汰类方案必须配一套专门的长程检索评测。
第二类是注意力本身的稀疏化。稠密注意力在长序列上的计算量随长度平方增长,这是长上下文里最贵的一块。稀疏注意力的思路是让每个 query 只 attend 到它认为相关的少数几个块上,重点不在保留哪几个 token,而在于如何用足够低的成本先找到可能相关的块。这里用到的分块、索引和前缀复用机制,与 KV 量化的失效模式并不完全一样:量化误差会随深度累积,稀疏注意力的错误则主要集中在相关块没被检索到这一种失效上。所以两者的评测必须分开设计,稀疏注意力要专门测那些答案藏在长文某个位置的任务。
把三者放在一起看,它们是互补而非竞争关系:稀疏注意力减少了需要计算的 KV 数量,KV 淘汰进一步减少了需要保存的数量,KV 量化降低了每个 KV 的存储成本。真实的长上下文系统很可能同时用上其中两种甚至三种。但顺序有讲究——如果选择性淘汰已经用掉了一半 KV 预算,再压到 INT4 带来的额外收益就有限了,这时更值得投入的是提高淘汰判据的准确率,而不是继续压位宽。位宽可以一直压下去,判据错了的代价却不会随之减小,这是两者最重要的非对称性。
五、剪枝:非结构化与结构化是两种命运
量化不改变模型的“形状”,它只是改变数字怎么存。剪枝改变的是模型里到底有多少个非零参数——这是两种性质完全不同的操作,它们的工程后果也完全相反。
5.1 核心矛盾:稀疏度和硬件利用率
一个理想的剪枝方案希望同时做到:高稀疏率(省显存)、规则的结构(能被硬件加速)、以及几乎无损的质量。现实是,这三条互相排斥:越自由的稀疏结构,越难被硬件利用;能被硬件利用的结构,恰恰是研究者专门去匹配硬件约束的结果。
原因在于通用 GPU 的执行模型。矩阵乘被分解成固定形状的 tile,每个 tile 由一组线程读取连续内存并做乘加。非零元素如果散落在内存各处,跳过的开销和读取的开销相当,甚至更高——你省下了乘加,却花在了访存上。这就是为什么随机非结构化剪枝在论文上有效、在生产上无效的根本原因:它的稀疏模式是给理论 FLOPs 省的,不是给实际硬件省的。
5.2 2:4 半结构化稀疏:唯一被硬件广泛支持的形式
2:4 是目前工程上最成功的剪枝格式,它的约束极其简单而精巧:在每连续 4 个权重元素中,恰好保留 2 个。这个约束的美妙之处在于它可以被编译成固定的稀疏计算模式——硬件按 2:4 的块加载两个非零值及其索引,所有被剪掉的权重在加载阶段就完全不会被触碰,没有浪费任何带宽。
它的代价同样明确:
- 上限是 50% 压缩。无论你的模型该剪掉多少,硬件格式的粒度决定了 2:4 就是 2:4。理论上更高的稀疏度在同样的块格式下不再带来访存收益。
- 需要真实硬件支持。只有较新的加速卡有对应的稀疏张量指令和两倍吞吐的承诺;在不支持的卡上,它会退化成 gather 加密集计算,反而比不剪更慢。上线前必须在目标机型上实测,不能看规格表。
- 索引要额外存。非零值之外的索引元数据要占空间,实际压缩比是 2:1 减去元数据开销,落到 1.6~1.8× 附近,比名义值低。
- 质量损失需要恢复训练。硬剪枝相当于对模型做了一次大幅度的、有偏的扰动,不做恢复训练会明显掉点。
实现上有一个常被忽略的细节:每 4 个元素的分组是沿权重展平后的连续维度切分的,而不是沿输出通道。这意味着一组 4 个元素可能跨越两个不同的输出滤波器,剪枝的语义和你在结构化直觉里想的完全不同。设计掩码时必须尊重这个展平顺序,否则剪掉的会是同一个滤波器的四个权重(那等于剪掉一个输出通道,损伤巨大),而不是分散的四个无关权重。
5.3 结构化剪枝:真正减少 FLOPs 的那种
结构化剪枝剪掉的是完整的通道、注意力头、FFN 中间维度、甚至整个 Transformer 层或专家。它之所以是唯一能真正省算力的剪枝方式,是因为被剪掉的部分在计算图里彻底消失了,不存在任何运行时判断。
不同粒度的结构化剪枝,代价差异很大:
| 剪枝对象 | 省什么 | 质量风险 | 恢复训练需求 | 实用判断 |
|---|---|---|---|---|
| FFN 中间维度 | 参数量与 FLOPs,比例可控 | 较低 | 中等 | 最常用;各层可以剪不同比例,按敏感性排序 |
| 注意力头 | 参数量与 KV 头数(连带省 KV) | 高 | 较高 | 头之间高度冗余,但剪错会直接损失能力;剪完通常要重新对齐 head_dim |
| Transformer 层 | 参数量与 FLOPs 同步下降 | 很高 | 很高 | 层是深度的骨架,剪层需要大量训练才能恢复;适合做深度剪枝研究 |
| MoE 专家 | 参数量可大幅下降 | 中 | 高(路由重训) | 本就是稀疏结构,裁剪专家比裁剪稠密层自然得多 |
| Embedding / LM Head | 参数量(词表大时占比可观) | 很高 | 不可行 | 基本不能剪,除非做词表裁剪并重训 embedding |
结构化剪枝的真正难点不是“剪掉多少”,而是“剪掉哪些”。常见的三类判据是:基于权重的幅度判据(最简单也最不靠谱,因为权重大小和重要性无关,这一点在 AWQ 那节已经讲过)、基于激活的判据(用校准数据看每个通道的输出幅度)、基于消融的判据(逐个剪了测影响,最准但成本不可接受)。实践中常用的是按层敏感度排序:先测量每层的重建误差,按误差从小到大依次剪,剪到目标比例停手。
5.4 恢复训练:决定剪枝成败的那一段
硬剪枝之后必须做恢复训练,这一点没有例外,但很多人低估了它的工作量。几个决定恢复效果的要点:
- 学习率要比预训练低一到两个数量级。恢复训练的目标是修补被扰动的权重,不是重塑表示。太高的学习率会把原有能力冲掉。
- 数据分布要对齐目标。用通用语料恢复、在特定任务上部署,恢复的效果会打折。
- 不要冻结大部分参数。常见做法是解冻所有层但用更小的学习率,或者只解冻被剪到的邻域层。全部冻结只训少数层,在高剪枝率下恢复不足。
- 稀疏格式必须在训练时就固定。2:4 的约束意味着每次更新后都要重新投影回合法掩码,训练循环里必须有这一步,否则会训出一个不满足格式的模型,最后部署时被硬件静默地错误处理。
还要注意一个容易被忽略的交互:剪枝之后再量化,量化的对象是恢复训练后的权重。如果你打算先剪后量化,恢复训练时就不该再用量化感知训练(QAT)去追一个已经被剪掉的量化误差目标,那是白费功夫;反过来,如果打算先量化再剪,剪掉的应该是一整个已经低比特化的块,粒度对齐会出问题。
5.5 一个特殊但很有价值的用法:把稠密权重转成稀疏专家结构
剪枝和 MoE 看起来方向相反——一个做减法,一个做加法。但它们之间存在一条非常有用的转化路径:把稠密模型里的 FFN 权重剪掉一部分,剩下的部分重新切分成若干个专家,从而在几乎不损失能力的前提下得到一个稀疏模型。
这条路径的价值在于它同时拿到了剪枝和稀疏激活两样的好处:模型确实变小了(总参数量下降),而每个 token 仍然只激活其中一小部分参数(保留条件计算的算力优势)。相比从零预训练一个稀疏架构,它便宜得多;相比单纯剪枝,它保留了让同样的总容量在不同输入上表现出不同行为的能力。
但转换不是免费的,有三个必须处理的点。第一,路由网络要重新训练:稠密 FFN 只有一个固定映射,拆成多专家之后需要一个负载均衡的分配机制,初始的 token 分配几乎一定是极度不均衡的(少数专家吃掉大部分 token),必须经过训练才能稳定。第二,专家间的容量差异:直接等分切分等于假设原 FFN 的不同通道段承担同等重要的功能,这个假设通常不成立,需要按重要性不均匀地分配容量。第三,剪枝率和专家数是耦合的:总参数量等于专家数乘以每专家参数量,两者要一起规划;而每 token 的实际计算量只由专家数单独决定——这两个数字在设计时经常被搞混,导致模型比预期大了很多却没快多少。
一个务实的建议是:这条路适合作为二次利用——已经训好的稠密模型想转成稀疏形态、或者有多个同架构不同领域的模型想合并成一个条件化模型——而不适合作为从零构建超大能力模型的路径。前者的成本以天计,后者的成本以月计,而且后者的效果也远好于任何转换技巧能拿到的结果。
六、蒸馏:把成本转移到数据上
前五种手段都是在不动模型拓扑的前提下重新表示已有权重。蒸馏是唯一一个真正换模型的手段——它用一个更小的学生去拟合教师的行为。它的收益上限最高(4B 学生追 70B 教师是完全可能的),它的成本也最高(需要教师推理 + 训练全流程)。
6.1 蒸馏不是“小模型学大模型”这么简单
把“蒸馏”当成一个单一方法会丢掉它最关键的信息。至少有三个层次:
- Logit 蒸馏:让学生在每个 token 上匹配教师的输出分布(温度缩放后的软标签,加真实标签)。它传递的信息远多于 one-hot 标签——软标签的暗知识包含了教师对其他候选的相对置信度,这正是学生从中学到的东西。
- 序列蒸馏:直接用教师生成的文本(而不是教师的 token 概率)训练学生,形式就是常规 SFT,只是数据来自教师。实现简单,但丢掉了分布信息,且会遇到教师输出多样性的问题。
- 推理链蒸馏:教师生成带完整思维链的答案,学生学着模仿。这在推理模型上尤其重要,因为推理能力的主要载体就是中间过程,只学最终答案学不到推理。
2025—2026 年一个明确的方法论转变值得单独说:离线蒸馏正在被在策略(on-policy)蒸馏取代。核心观察是,离线蒸馏训练的学生只能在自己能力分布之外模仿教师的文本——学生在自己会犯错的 token 位置上,从来没有被教师“拉回”过,因为它没有在这些位置采样过。在策略蒸馏让学生自己生成序列,然后由教师在学生实际访问到的状态上给出监督信号,从而直接纠正学生的具体错误。机制上它把学习问题从“模仿一个分布”变成“在关键状态上做纠正”,这在推理任务上带来的差距通常远大于两者在算力上的差距。
6.2 数据构造:蒸馏质量的天花板
蒸馏的效果上限往往由数据构造决定,而不是由训练配方决定。几个决定性的变量:
| 环节 | 做法 | 踩坑点 |
|---|---|---|
| 题目来源 | 公开数据集、真实用户日志、合成题目 | 合成题目容易同质化,教师在熟悉的模式上输出模板化答案,学生学不到边界行为 |
| 教师采样 | 多个温度多次采样,用判别器或规则筛出正确的那些 | 只用温度 0 的贪心输出,样本多样性不足,学生过拟合到教师的单一路径 |
| 质量过滤 | 规则校验、执行验证、多模型交叉判定、去重 | 不验证就收,教师在长尾问题上会产出流畅但错误的数据,错误会被完整地蒸馏给学生 |
| 难度分布 | 刻意保留一批难题 | 只留教师能轻松解的题,数据全部落在学生的舒适区,蒸馏出的提升上限很低 |
| 去污染 | 与评测集比对 n-gram 和语义相似度 | 不做去污染,蒸馏出的“高分”里有一部分是记忆,评测会严重高估 |
| 格式一致性 | 统一思维链的格式和长度风格 | 教师自身的思维链冗长且重复,学生照抄后推理 token 数暴涨,成本反而上升 |
其中两条最值得强调。第一,验证是蒸馏数据管线的必备环节,不是可选项。教师模型的错误率在困难任务上并不低,而学生的模仿能力很强——它会连错误模式一起学。没有验证的蒸馏是在放大教师的弱点。
第二,难度分布比数据量更重要。这是很多人不理解的地方:蒸馏的学习信号主要来自学生犯错而教师不犯错的那些位置。如果数据里绝大部分是教师和学生都会的简单题,那么这类 token 上教师提供的软标签信息量极低,训练几乎不产生梯度。真正有价值的是能力差区域的数据。实践中这意味着要按学生当前的能力动态调整采样难度,这是一个持续演化的数据生产过程,而不是一次性的数据准备。
6.3 师生能力差:什么时候蒸馏会失效
蒸馏有一个被反复观察到的现象:当教师与学生的能力差距过大时,蒸馏的收益会急剧下降,甚至低于直接从教师的输出做 SFT。原因不难理解——学生没有足够的基础表示来承接教师的高阶行为,它学到的只是教师的表层形式(句式、格式、术语),而不是推理结构,同时被大量的、它无法消化的错误推理步骤带偏。
实践中的判断依据有两条。第一条是看教师的思维链是否可学:如果教师的推理链条长到学生根本走不到正确的中间状态,那么无论怎么采样,梯度信号都是噪声。第二条是看难度匹配的分布:把教师和学生分别在验证集上跑一遍,统计学生“会但不确定”和“完全不会”的比例。如果前者占比很低,说明数据全部落在能力差区域之外,需要降低教师规模或者先做一轮 SFT 补底。
由此推出一个稳健的策略:分层蒸馏。先用最大的教师(可能伴随最强但最冗长的推理过程)做一轮 SFT 铺底,然后换用与当前学生能力更匹配的教师做多轮在策略蒸馏。每一轮都重新评估能力差,据此调整难度分布。这本质上是一个课程学习问题,而不是一次性的数据搬运。
蒸馏的收益主要来自师生能力差区域的数据。当学生已经在某个维度上追平教师,那个维度上继续蒸馏的边际收益接近零,应该把算力挪到还有差距的维度上。
6.4 蒸馏效果怎么单独测
蒸馏模型和量化模型有一个本质区别:它的质量不是由某个公式直接算出来的,而是训练出来的。这意味着评测一个蒸馏模型,必须能区分学生真的学会了,和学生只是在模仿教师的表面形式,而只用一个总体分数是看不出来的。
有三条必须分开测的线索。第一条是能力差曲线:在学生和教师之间做插值,测不同插值点的性能。如果曲线在接近教师的一侧仍然明显低于教师,说明学生不是学得不够,而是容量不够——那么继续加数据没有用,该换更大的学生,或者把任务分布收窄。这是区分“数据不够”和“学生太小”最重要的一条线,而它只需要一次插值实验就能得到。
第二条是教师的错误是否被继承。在学生必然答错的题目上,比较学生和教师的答案分布有多接近。如果高度接近,说明学生在模仿教师的错误。这一步必须在教师的低置信区域采样才能测出来,在学生有把握的样本上测是没有意义的。它也是蒸馏数据验证环节是否真的起了作用的最直接证据——如果验证没做或做得不够,这条曲线会明显偏高。
第三条是在策略与离线的对照:用同一位教师、同样规模的算力预算,分别做一次离线蒸馏和一次在策略蒸馏,比较结果。这个对照不需要很大规模就能看出方向,但它经常是决定要不要把整条数据生产流程改造成在策略的唯一依据——因为流程改造的成本不小,需要有数据支撑才能立项。
把这三条合起来,蒸馏的评测逻辑是:先确认容量够不够,再确认学得对不对,最后确认方法选得对。跳过第一条去优化数据,或者跳过第三条就改造整条数据管线,都是常见的时间浪费。
七、稀疏化:权重稀疏与激活稀疏是两种东西
前面讲的 2:4 和结构化剪枝都属于权重稀疏——决定哪些权重参数被永久丢弃。但还有另一条完全不同的路:在运行时决定哪些计算这一步不做。这一族的统称是激活稀疏(或动态稀疏)。
7.1 权重稀疏:静态、可预测、硬件友好度低
权重稀疏的决策在训练或剪枝阶段一次性完成,推理时是一张固定的掩码。优点是可预测——你知道每层每步会做多少计算,而且可以离线预排布。缺点是它对硬件极不友好:掩码的存在本身不保证任何加速,通用 GPU 只有在 2:4 这类固定格式上才提供真实收益。更根本的是,权重的零并不等于计算的零——一个被剪掉的权重如果对应的激活恰好是那个时刻的大值,损失是真实的,但稀疏格式并不会因此区别对待它。
7.2 激活稀疏:动态、硬件收益大、精度损失也更大
激活稀疏的逻辑完全不同:权重保持稠密,而是在乘加时根据激活的幅度跳过一部分乘法。因为激活是每步动态的,所以跳过哪些也是动态的,这天然适配运行时稀疏。
它的技术核心是预测:要在真正做乘加之前就知道哪些激活会小到可以跳过,而这只能靠预测——要么用低秩近似预测激活的模长,要么干脆用真实激活的下采样统计来近似。预测不准就有两个后果:漏掉了本该保留的大值(精度损失),或者保留了本该跳过的小值(稀疏率不达标)。
这类方法在 2023—2024 年被认真研究过,结论是:它们在纯粹的 FLOPs 节省上非常可观,但在真实的端到端推理服务上很难兑现。原因在第一节已经说过——稀疏度提高的是理论算术强度,但服务往往还受限于访存、kernel 调度、以及稀疏模式引入的 gather 开销。加上 Transformer 里 FFN 的中间维度只有几千、且被放大器后的激活分布相当平坦(很难找到足够多的小值),能安全跳过的比例往往达不到理论值。
| 维度 | 权重稀疏(2:4) | 激活稀疏 |
|---|---|---|
| 决策时机 | 训练/剪枝时,一次性 | 每个推理步骤,动态 |
| 省显存 | 是(1.6~2×,含元数据) | 否 |
| 省 FLOPs | 依赖稀疏核 | 是(但需要预测器开销) |
| 硬件支持 | 新卡原生支持 2:4 | 通用 gather 计算,收益不确定 |
| 精度风险 | 低,掩码可预测 | 高,预测错误直接损失精度 |
| 可解释性 | 高 | 低,需额外分析 |
| 2026 年判断 | 生产可用,需匹配硬件 | 研究阶段,端到端收益不稳定 |
与激活稀疏相邻的还有 MoE 式的动态稀疏——通过 MoE 路由让每个 token 只激活少数专家。这在“动态稀疏”这一栏里是唯一被大规模生产验证过的形态。它的关键区别在于:MoE 的稀疏性来自参数量的扩张(总参数更多、每 token 激活更少),而不是来自参数的删除。它的显存账是反的——MoE 让显存需求上升、FLOPs 下降。所以 MoE 不是一个压缩手段,它是用显存换算力的架构选择,恰好和压缩的方向相反。把 MoE 当成“压缩”来宣传是概念错误。
7.3 动态 token 剪枝与早退:稀疏化在推理时的新形态
前面两节讨论的都是权重侧的静态稀疏,但稀疏化在推理阶段还有两个正在变得重要的形态,它们不减少参数,只是决定这一步不做什么。
第一个是prefill 阶段的 token 剪枝。长上下文的开销主要发生在预填充阶段,而这一阶段处理的绝大多数 token 对最终答案的贡献微乎其微——一整段背景材料里,可能只有两三句真正相关。做法是先用一个廉价的判据(通常是 attention 分数的粗略估计,或者一个很小的辅助打分模型)识别出低贡献的 token,在进入主体计算之前就丢弃它们。这和 KV 淘汰的区别在于时机:KV 淘汰发生在解码期,prefill 剪枝发生在注意力矩阵被完整计算出来之前,因此省的不只是存储,还有平方级的计算。它的风险也和 KV 淘汰同源:判据丢掉了一个关键 token,模型会自信地基于残缺信息作答,而且不会有任何报错。
第二个是逐 token 早退。简单请求的答案往往在少数几个解码步之后就已经确定了,继续生成几十个 token 只是把一个已经稳定的答案继续写下去。逐 token 早退的思路是给解码过程加一个轻量的判据(常见做法是看隐藏状态的变化幅度,或者用一个极小的分类头判断当前答案是否已闭合),一旦判定收敛就提前停止并补上结束符。它和级联路由是同一个直觉在不同粒度上的实现:不是每个 token 都值得花同样的代价去生成。这类方法的风险是判据把“还没想完”误判为“已经收敛”,提前截断会直接造成答案不完整——而且截断掉的往往正是推理链最关键的后半段。
把这两个形态放进来,一个统一的视角就出现了:压缩的本质是判断哪些计算可以不做。权重量化是按数值重要性判断(离群值、小权重被舍),剪枝是按参数重要性判断,KV 淘汰和 token 剪枝是按内容重要性判断,早退和级联是按难度判断。区别只在于这个判断的可靠性来自哪里——来自数值的判断最可靠但最粗糙,来自学习的判断最精细但最脆弱。所以生产系统里真正稳的做法,是把可靠的粗判断(量化、低位宽剪枝)作为基础,把脆弱的细判断(淘汰、路由)限制在收益明确且能被评测覆盖的范围内。
八、三者叠加:误差会叠加,收益不会
到这里可以处理最难的问题了:能不能把量化、剪枝、蒸馏一起上?答案是可以,但叠加效应既不是线性的也不是加性的,必须逐个验证。
8.1 一个必须先建立的直觉:三类误差的性质不同
把三种手段的误差放在同一个视角下看,会发现它们其实作用于模型的不同位置:
- 量化误差:权重侧或激活侧的高频小扰动。它是局部、密集、每层都有的,作用在每一个权重/激活上。
- 剪枝的损失:结构性的、稀疏、一次性的容量移除。它删除的是特定的参数(结构化)或固定的模式(非结构化)。
- 蒸馏的误差:全局、目标导向的。蒸馏过程会用训练去主动补偿压缩带来的损失——它是在有损压缩之后做的一次有监督修复。
这个性质差异立刻推出一个重要结论:因为蒸馏的误差是训练出来的、可以看到量化与剪枝后的模型的行为的,所以“先压后蒸”在原理上优于“先蒸后压”。先蒸出一个好学生,再对它做量化和剪枝,等于在压缩之后没有任何补偿机制;先压再蒸,蒸馏阶段可以把压缩损失当作要拟合的目标来修。这个顺序不是偏好问题,是机制问题。
8.2 具体的干扰点
几种具体的互相干扰值得单独列出:
- 剪枝和量化的粒度冲突(最严重的一个)。2:4 的约束是沿展平后的连续 4 元素分组,而 group-wise 量化的分组也是沿连续维度切的。如果先做 group-wise 量化再剪枝,剪掉的两个非零值可能破坏量化组的 scale 统计;如果先剪枝再量化,被剪掉的值如果是某组里的离群值,整组的 scale 会被重新计算,反而变好了。实践上应该先剪枝后量化,让量化器看到剪枝后的最终分布。
- 量化与恢复训练的循环依赖。如果你对 2:4 剪枝做恢复训练,同时又用量化感知训练,两者会争夺同一个目标:恢复训练想找回剪枝掉的容量,QAT 想让权重更抗量化。实践中的做法是分阶段——先剪枝 + 恢复训练到收敛,再冻结掩码做 QAT 微调最后一小段。不要试图同时优化。
- 蒸馏数据与压缩后模型的不匹配。教师生成的推理链是针对未压缩的能力水平生成的。如果对压缩后的学生做离线蒸馏,学生看到的教师轨迹是它自己走不到的状态,前面说过的能力差问题会被放大。在策略蒸馏在这里的价值特别高,因为它天然针对学生的实际弱点采样。
- 离群值处理的顺序。旋转类前处理应该放在量化之前,但如果同时做结构化剪枝,旋转之后再剪枝,剪枝判据看到的分布已经不是原始分布了。旋转的逆变换是正交的,不改变数值大小关系,所以一般安全;但如果你用基于幅度的判据选要剪的通道,顺序仍然重要。
8.3 叠加顺序的推荐与实测
综合上面的分析,一个通用的叠加顺序是:
- 结构化剪枝(如果要做)——因为它改变模型形状,必须最先做,且为后续所有步骤减少参数量。
- 恢复训练——补回剪枝的容量。注意这一步要在低精度之前做,高精度下恢复效果最好。
- 蒸馏(如果要做)——用教师数据训练这个已经剪过枝的模型,让它对齐教师。此时剪枝损失和任何初步的低精度影响都会被一并补偿。
- 旋转 / 通道缩放等前处理——基于最终模型的实际激活分布来估计。
- 权重量化——作为最后的表示变换,它的误差不再有任何机制去补偿。
- KV 量化——与权重正交,可并行推进,单独评测。
但这个顺序只是起点,必须实测验证。一个具体的验证方法是做增量消融:从 BF16 基线出发,一次只加一个手段,记录质量变化;然后两两组合、三三组合,逐步堆叠。如果发现某个组合的损失超过各单独损失之和(负向交互),那说明两个手段在争抢同一个东西,需要调整顺序或其中一个的强度。
| 组合 | 是否推荐 | 理由 | 注意 |
|---|---|---|---|
| 权重量化 + KV 量化 | 强烈推荐 | 两者作用于不同张量,误差不共享路径 | 分别评测,不要合并成一个数字 |
| 权重量化 + 激活量化 | 推荐 | W4A8 是成熟形态,但需要先做旋转前处理 | kernel 支持是前提,量化的激活精度通常要 8bit |
| 结构化剪枝 + 权重量化 | 推荐 | 先剪后量化,量化器看到最终分布 | 剪枝后的模型更小,可以用更大的 group size 换质量 |
| 2:4 剪枝 + 4bit 量化 | 谨慎 | 两者都在权重上,粒度冲突严重 | 必须先剪后量;实际收益可能不如单用一个 |
| 量化 + 蒸馏 | 推荐,顺序为量化后蒸馏 | 蒸馏的补偿能力正好发挥作用 | 用量化后的模型去生成蒸馏数据会更准确,但成本高 |
| 剪枝 + 蒸馏 | 推荐 | 剪枝减容量、蒸馏补能力,配合自然 | 恢复训练和蒸馏可以合并成一次训练 |
| 三者全上 | 可以,但收益递减明显 | 叠加收益通常在第二种手段之后急剧下降 | 必须做增量消融,验证是否有负向交互 |
最后一个必须说的现实判断:叠加的边际收益递减得非常快。单独从 16bit 到 8bit 质量几乎不掉,从 8bit 到 4bit 掉一点,4bit 再往下就很难了。同理,剪枝 20% 的损失可能很小,剪到 50% 就要大量恢复训练。所以当你想同时上三种手段时,诚实的预期应该是:第一项拿到了大部分收益,第二三项各补上一小块,而交互项可能会吃掉其中一部分。如果时间有限,只上收益最大的那一项通常是最优决策。
8.4 组合之外的第三条路:把不同压缩度的模型串成级联
前面讨论的所有方法都作用在同一个模型上。但工程上还有一种完全不同、而且往往比任何单一压缩方案都更有效的做法:准备多个压缩程度不同的版本,用路由决定每个请求交给哪一个。
最常见的形式是级联:小而快的模型先做,遇到不确定或高风险的请求再转交大模型。它的价值来自一个常被忽略的事实——不同请求的难度分布极度不均匀。大量日常请求是格式转换、常识问答、简单改写,这些请求在最强模型上做和在有损压缩过的模型上做,结果几乎一样;而少量请求需要长链推理,这些在压缩模型上做会明显掉点。按请求分配算力,比对所有请求统一压缩要划算得多。
级联和压缩的配合点很明确:级联的收益上限由最弱那一档决定。如果所有版本都用 BF16,最便宜的那一档仍然很贵,级联的省钱效果有限;先把最弱一档压到 4bit 或 6bit,级联的整体成本才真正下降。反过来,压缩得越狠,路由器的容错空间越小——一个不确定度估计不准的路由器,配上质量更差的模型,会把本该升级的请求留在低档,产生平均质量掉得比预期更多的结果。所以路由的准确率是级联系统的核心指标,它比任何单档的压缩指标都重要,评测时要单独测误升级率(不该升级却升级了,浪费成本)和漏升级率(该升级却没升级,损失质量)。
另一种更简单的形态是按任务类型静态路由:确定简单的业务流量固定走小模型,复杂流量固定走大模型,不需要任何运行时判断。牺牲掉一部分灵活性,换来完全可预测的延迟和成本。在请求特征容易被分类的场景,这通常是更好的工程选择,因为运行时不确定性本身就是一类成本。
最后要提醒一个决策层面的事实:级联是压缩的替代方案,不是补充。当流量难度分布足够偏斜时,一个小模型加一个大模型的组合成本,可能已经低于让一个中等模型全量承担。所以在投入精细的压缩调优之前,先测一下请求的难度分布——如果 80% 的请求其实很简单,那么把预算花在级联路由上的回报,通常远高于把 4bit 优化到 3.6bit。
8.5 压缩与微调的接口:顺序决定成本
压缩不是训练流程的终点,而常常是中点。因为在多数情况下,压缩之后还要再微调一轮,而这一轮放在哪里,会让成本差出好几倍。
先说最重要的一条原则:量化感知微调应该在压缩方案确定之后再做,而不是用来帮你选方案。很多人会在选位宽时先上一轮量化感知微调,发现质量回来了就认为这个位宽可行——这是一种循环论证。量化感知微调确实能让一个偏激进的配置变得可用,但它掩盖了“这个配置本身有多勉强”这个关键信息。正确做法是先用不依赖训练的量化测出质量底线,再决定是否值得花一轮微调把它救回来。
接下来是几条具体的顺序规则。剪枝之后必须做恢复训练,而且这一轮不要同时做量化感知:剪枝已经是一次大幅度的结构扰动,恢复训练的目标是把容量找回来,同时压制量化误差会让两个互相矛盾的目标互相干扰,常见的结果是两件事都只做到一半。更稳的安排是先在高精度下把剪枝恢复到位,再冻结掩码、切换到量化配置,用很短的一段微调让权重适配新的表示。
蒸馏和微调可以合并成一轮。如果最终方案里既有剪枝又有蒸馏,就没有必要先恢复训练再蒸馏两次——把教师的输出作为这唯一一轮训练的目标,同时保持剪枝掩码固定,两个目标就在同一次优化里被处理了。这比两次串行的训练便宜得多,也通常效果更好,因为恢复训练和蒸馏都在改同一批权重,分开做会让后一阶段把前一阶段的成果重新洗掉一部分。
低秩适配和量化可以共存,但角色要分清:低秩适配负责给模型注入任务相关的新能力,量化负责让基座能装进显存。两者不冲突,但要注意适配矩阵在量化之后是否也保持低精度——如果适配层是高精度而基座是四比特,那么推理时的精度差异会集中体现在适配层上,评测时容易把适配层的问题误判成量化的问题。一个稳妥的做法是让适配层的精度与基座保持一致,或者至少在评测时把两者分别验证。
最后是压缩之后微调的数据分布:用压缩前的模型生成的数据去微调压缩后的模型,会引入一个隐性的分布错配——数据的风格来自一个能力更强、精度更高的模型,而接受这些数据的模型已经是有损的。经验上,用压缩后的模型自己重新生成一遍适配数据效果通常更好,尽管多了一次数据生成的成本。
把这一节压缩成一句话:压缩方案一旦定型,后面的微调才真正开始;微调不能用来挽救一个本来就该被否决的压缩方案,它只能锦上添花。这个判断能省下最贵的那类浪费——花一周微调去救一个本该在第一天就否掉的激进配置。
九、怎么判断压缩到底有没有真的划算
压缩项目最常见的失败模式不是技术做不出来,而是做出来了却说不清收益。下面是一套可以直接落地的评测方法,核心是把质量、显存、速度、成本放在同一个报告里,用一个净收益指标收口。
9.1 先分清名义压缩比和有效压缩比
大部分报告里的“4× 压缩”是名义压缩比:4bit 除以 16bit。有效压缩比要把所有附带开销算进去:
有效权重压缩比 = (基线权重字节数) / (量化后权重字节数 + scale + zero_point + 未压缩的例外值 + 未融合算子工作区)
# 分组元数据开销的快速估算(对称 INT4,每组 128 元素)
overhead_bits_per_weight = (16 + 4) / 128 # FP16 scale + 4bit 零点
actual_bits_per_weight = 4 + overhead_bits_per_weight # ≈ 4.156
# 2:4 稀疏的实际情况(每 4 个元素存 2 个值 + 2 位索引)
sparse_effective_ratio = 2 * 1.0 / (1.0 + 2/16) # ≈ 1.78x,而非 2.0x
KV 侧同理:INT4 KV 配 group 64 加 scale 之后,实际每元素 bit 数大约是 4 加 20/64,也就是 4.3 bit 左右,不是 4。报告里写“4×”和写“3.7×”反映的是不同的严谨程度,而下游做容量规划的人需要的是后者。
9.2 质量评测:必须分层,而且必须有任务级的终局指标
困惑度(perplexity)是最容易算的指标,也是最不能单独作为决策依据的指标——它和实际任务表现的相关性很弱,尤其在经过剪枝和蒸馏之后,困惑度可能完全不动而任务准确率明显变化。建议的评测分层:
- 第 0 层:困惑度。只作为快速回归检查,用来发现灾难性错误(比如某个层的量化出错了)。不要用它做决策。
- 第 1 层:通用能力基线。固定几个覆盖面广的基准,测相对基线的绝对分数变化,不是相对变化百分比。
- 第 2 层:目标能力。你的实际任务集,权重最高。这一层如果掉了,前面几层再好也没意义。
- 第 3 层:压缩敏感任务。专门挑那些已知对误差敏感的子集:长上下文检索、多步推理、精确的代码生成、需要数学校验的题目。KV 量化会先在前者崩,结构化剪枝会在后两者崩,而常规基准可能完全测不出来。
- 第 4 层:行为退化检查。不只是分数,还有输出形态:回答长度是否剧增、是否开始重复、拒答率是否上升、格式遵循是否破坏。这些是压缩模型最常见、也最容易被忽略的退化方式。
评测纪律上至少有三条硬要求:采样参数完全固定(贪心解码、温度为 0,引入采样噪声会掩盖压缩带来的差异);多个随机种子或至少记录完整的评测配置;以及基线和压缩版本必须在同一硬件、同一 batch 配置、同一并发压力下测——否则性能数字不可比。
9.3 系统评测:按你的真实流量形状测,而不是按实验室形状
性能评测的常见错误是只测单请求延迟。压缩的收益高度依赖负载形状,必须至少测三个点:
| 测试点 | 配置 | 主要观察 | 典型结论 |
|---|---|---|---|
| 单请求 | batch=1,短输入 | TTFT、TPOT、端到端延迟 | 权重量化的收益在这里最明显,接近线性 |
| 大 batch | batch 填满,固定长度 | 吞吐、是否转为算力受限 | 权重量化收益衰减,激活量化才开始起作用 |
| 长上下文 | 输入长度拉到 8K~128K | KV 显存、随长度的延迟增长斜率 | KV 量化的收益随长度线性放大 |
| 混合真实流量 | 用生产日志的长度分布回放 | 综合成本、p99 延迟 | 唯一能反映真实 ROI 的数字 |
同时要记录显存占用(用峰值分配量而不是保留量,后者受缓存池影响会虚高),以及模型加载时间和冷启动——一个 36 GB 的模型和一个 140 GB 的模型,在按需扩缩容的架构里,启动时间是真实成本。
9.4 净收益:把决策收敛到一个数
把质量损失换算成可承受的阈值,是让压缩决策可落地的关键。定义一个净收益指标:
# 净收益:节省的月成本 减去 质量退化带来的月损失
monthly_saving = (baseline_gpu_count - compressed_gpu_count) * gpu_price_per_hour * hours_per_month
quality_loss_pct = max(0, (baseline_score - compressed_score) / baseline_score)
# 把质量损失换算成业务影响(需要按任务实际估算,这里是结构)
monthly_quality_cost = quality_loss_pct * affected_volume * value_per_request
net_benefit = monthly_saving - monthly_quality_cost
# 决策:净收益为正且质量损失低于业务容忍阈值才上线
# 注意:质量损失必须用绝对分数差判断,不能用相对百分比
这个公式的重点不在数学,在它强迫你为“质量掉了多少”标一个真实的价格。很多压缩项目停在“我们省了 40% 显存”就没往下走了,因为一旦要回答“掉 1.2 分能不能接受”,就会发现不同的 1.2 分对不同业务的意义天差地别——对内部摘要任务无所谓,对合同审阅就有问题。压缩方案的选择本质上是在业务容忍度约束下求最小成本,而不是一个纯粹的技术优化问题。
9.5 落地检查清单
把上面所有内容压缩成一个可执行的顺序:
- 先测瓶颈:用生产的长度分布和并发数,确认是带宽受限还是算力受限。
- 先做无损的那一步:GQA 已经是低配的情况下,先看 KV head 数和 batch 调度;确认瓶颈在权重而不是 KV。
- 权重侧从 8bit 起步:INT8 或 FP8 的 group-wise 量化通常是安全的,收益已占大头,先确认这一步的质量基线可信。
- 再考虑 4bit:配 per-group 128,用目标任务数据校准,GPTQ 家族 + 通道缩放。
- 长上下文单独走 KV 量化:per-token 的 FP8 或 INT8,独立评测,重点测检索任务。
- 只有当质量还有明确余量时才碰剪枝:先结构化后非结构化,每次都配恢复训练。
- 蒸馏放在最后作为补偿层,顺序是“压缩后蒸馏”,而不是反过来。
- 全部动作进增量消融表:每加一项就重跑质量与系统两组评测,任何一项出现非线性下跌就停下来重新分析交互。
- 记录完整的配置快照:量化参数、校准集哈希、随机种子、kernel 版本、驱动版本。压缩模型的可复现性比普通模型脆弱得多,缺一个记录几个月后基本无法重造。
9.6 六个最常见的翻车现场
最后把实践中最容易出问题的地方集中列一遍。这些几乎每一项都真实发生过,而且大多不会抛异常,只会安静地让结论变差。
- 拿推理框架的默认值当基线。基线必须是明确配置的 BF16 原始权重版本,而不是某个框架自动选出的最优配置,否则测出来的收益里混着框架的自动优化,压缩本身的贡献无法归因。
- 量化版本和基线用了不同的采样参数。温度不为 0 时,采样噪声通常大于压缩带来的差异,测出来是两者没差别,实际是有差别但被噪声埋掉了。所有对比评测都应当用贪心解码。
- 只看困惑度就上线。困惑度对剪枝和量化都不敏感,一个明显退化的模型可以困惑度几乎不变。至少要有一个任务级的分数作为门槛。
- 忘记评测长上下文。KV 量化、注意力头剪枝、稀疏注意力的收益和风险全都集中在长序列上,只用短上下文评测等于没有测最关键的那部分。
- 忽略输入长度分布的变化。把模型从 4K 上下文用到 128K,而量化校准只见过 4K 以内的样本,某些依赖校准时统计特性的方案会在超出范围之后失效。
- 把压缩当成一次性的配置。量化参数、剪枝掩码、路由权重、蒸馏数据配方之间是有依赖的。后续换了基座模型、换了推理框架版本、或者改了校准数据,之前的评测结论就不适用了,必须重跑而不是引用旧结果。
这六条的共同点是:它们都不会抛异常,只会让结论悄悄失真。所以压缩项目最需要投入的往往不是更精巧的量化算法,而是一套能持续复现、能定位变量、并且不省略长上下文分支的评测流程。算法选型可以试错,评测失真则会让所有的试错都指向错误的方向。
9.7 别忘了评测本身也有成本
一次完整的压缩评测不是跑一遍基准那么简单,它的成本经常被低估,而这会直接影响你能测多少个方案、结论有多可靠。下面几笔账必须预先算清。
- 时间成本:一次完整评测的绝对时长决定了你能做多少次对照。如果单次评测要跑一整天,那么用不同随机种子跑三次就是三天,方案迭代速度会慢到无法收敛。实际做法是用小规模子集做快速筛选,只让入围的方案跑完整评测,而不是所有方案都走同一套完整流程。
- 层级成本:第 0 层的困惑度几分钟就能算完,第 2 层的目标能力评测可能要几小时。把这两层混在一起会让迭代极其昂贵。分层的意义不只是评测逻辑清晰,更是让便宜的判据负责淘汰,昂贵的判据负责定案。
- 重复性成本:量化方案的评测对随机性敏感,来源包括校准集的切分方式和推理时的采样。同一方案跑两次得到不同结论时,不能靠再跑一次取更好的结果来解决,那是在做选择性报告。要么固定随机源,要么用足够多的重复次数给出置信区间。
- 维护成本:只有完整记录了量化参数、校准集哈希、kernel 版本、框架版本和驱动版本的评测结果,才能在几个月后被复现。压缩栈里的任何一层升级都可能改变结论,所以评测环境的版本必须和模型配置一起被版本化,否则跨时间的对比全都无效。
把这几笔账算清楚之后,会得到一个现实但常被忽视的推论:你不需要把所有可能的压缩组合都测一遍。第十节给出的顺序本身就是一个按先验收益排序的搜索路径,先跑高概率的组合,把评测预算留给真正有歧义的分叉点。这比穷举更省时间,也更容易收敛出可靠结论。反过来说,一个只有三天评测预算的项目,应该主动砍掉方案数量,而不是压缩评测的严格程度——后者是唯一不能省的地方。
9.8 压缩模型上线之后:维护与漂移
压缩配置不是一次性交付物,它是一份需要长期照看的配置。上线之后真正会发生的事,通常不是模型突然坏掉,而是结论慢慢失效而没人察觉。以下几类漂移值得在流程里显式监控。
- 推理栈升级带来的数值漂移。kernel 的实现、归约顺序、累加精度都会随着框架或驱动版本变化。同一份权重在不同版本上跑出略有不同的结果属于正常现象;但如果差异随时间单调增大,说明某个环节的数值语义已经变了,需要重新评测,而不是继续沿用旧结论。
- 上游权重更新带来的失效。如果基座模型被替换或继续训练,压缩配置里的量化参数、剪枝掩码、蒸馏数据配方全部作废——它们都是针对特定权重拟合出来的。必须为每个权重版本单独记录并验证压缩配置,不能想当然地继承上一版的结论。
- 流量分布漂移带来的隐性退化。压缩方案是在某个输入分布上校准和评测的。线上流量的长度、语言、任务类型分布会变化,激活的数值范围随之变化,量化参数就偏离了当初校准时的假设。这类问题不会体现在离线评测上(因为离线分布本身没变),只能靠线上抽样回测发现。
- 质量漂移的观测方式。压缩模型的线上质量下降往往是渐进的:输出变啰嗦、开始重复、在边缘问题上给出格式不合规的答案。这些都不需要标注数据就能被发现——定期抽样人工看,加上对输出长度分布、重复率、拒答率的监控,通常比等业务指标下跌更早发现问题。
对应的实践建议是三条:把压缩配置和权重版本绑定在一起做版本管理,任何一个变了都要重新跑评测;在推理栈升级的发布流程里加上回归评测这一环,把它和功能测试放在同一个关卡;以及定期用线上真实分布抽样回测,即使离线指标没变,因为分布本身已经变了。
这三条的共同逻辑是:压缩方案的有效性依赖三个隐含假设——权重没变、推理栈没变、输入分布没变。任何一条被打破,原有的评测结论就不再自动成立。把这三条假设显式写进上线检查单,比事后排查便宜得多。
十、总结:压缩是一组决策,不是一种技术
回到开头的判断:压缩首先省的是存储和搬运,只有当瓶颈在带宽上时才转化成速度;权重量化不碰 KV Cache,激活量化才碰 FLOPs;蒸馏是唯一全维度有效但成本也最高的手段。这三个判断决定了其他所有选择。
具体到方法上:量化是最普适的一档,它的旋钮是位宽(省多少)和分组粒度(省得值不值),现代 PTQ 的差异主要来自是否做了激活感知的通道缩放和旋转前处理;GPTQ 和 AWQ 回答的是不同层面的问题,实践中经常叠加使用而非二选一。剪枝的成败由硬件格式决定,2:4 是当前唯一被广泛硬件支持的形式,结构化剪枝是唯一真省算力的形式,两者都必须配恢复训练。蒸馏的上限由数据构造决定,能力差区域的数据才是有效学习信号,在策略方法比离线方法更有针对性。
而三者叠加时最重要的机制性结论只有一条:因为蒸馏是在有损压缩之后做监督补偿,所以顺序应该是“剪枝 → 恢复训练 → 蒸馏 → 量化”,量化放在最后。因为它没有补偿机制,越晚做损失越难挽回;剪枝必须在量化之前,因为两者的分组粒度会冲突。
最后,关于如何判断“真的划算”,只有一个真正的答案:用你真实的流量形状、真实的任务分布、真实的业务容忍度,去算那一个净收益数字。所有不落到这个数字上的压缩报告,都还只是技术展示。真正的工程决策从来不是“能不能压”,而是“压掉的这部分质量,值不值省下来的这些算力”。