ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

INT8量化部署实战:从PTQ校准到QAT与LLM量化的完整路径

INT8量化部署实战:从PTQ校准到QAT与LLM量化的完整路径 量化这两年几乎成了部署必选项。模型训完想往生产环境放要么卡在显存不够要么延迟打不进预算而 INT8 量化恰好能把这两件事同时往前推一大截。我平时主要做推理侧的服务部署也经常在边缘设备上调模型这篇就把我实际跑通 INT8 量化、校准、QAT 以及 LLM 量化这几条路径的笔记整理出来尽量讲清楚每一步在做什么、为什么非做不可、以及哪些地方容易翻车。1. 为什么量化能提速提速的钱到底从哪来很多人一听说量化就直觉以为模型变小了所以快了。模型变小只是收益之一真正的提速来自三个层面的联动。1.1 数据搬运量直接减半先看一个数字FP32 一个数占 4 字节FP16 占 2 字节INT8 只占 1 字节。推理过程里每一层都要从内存里把上一层的输出搬进计算单元这个搬运成本在真实部署里往往比计算本身还贵。算子算得再快数据喂不上来也是白等。把激活值从 FP16 换成 INT8单次搬运的字节数直接砍一半从 FP32 换成 INT8直接砍四分之三。对于内存带宽吃紧的设备CPU、树莓派这类小板子、还有部分手机 NPU这个收益立竿见影。1.2 硬件对低精度计算偏心这不是软件优化是硬件设计上就偏心。现代 GPU 的 Tensor Core 对 INT8 的吞吐通常是 FP16 的两倍有些架构甚至是四倍CPU 上也有对应的 INT8 指令集比如 AVX512_VNNI、ARM 的 SDOT都支持一条指令打包多个 INT8 乘法。NPU 就更不用说了INT8 基本是各家边缘芯片的主力数据类型。我在 NVIDIA 的卡上实测过同一份推理代码从 FP16 切到 INT8算力密集型的卷积层吞吐基本能翻倍。CPU 上虽然没有那么夸张但配合带宽优势整体延迟也能看到明显回落。1.3 功耗和部署形态的连带收益量化之后模型占用内存变小缓存命中率提高功耗随之下降。手机端、摄像头端的场景特别吃这个。有时候模型没量化前跑在边缘设备上直接过热降频量化完反而能稳定运行。这块的收益不体现在跑分脚本里但体现在真实设备体验上。一个容易忽略的点量化之后单个设备能同时承载的模型实例变多。比如同一块 GPUFP16 能塞下 8 个实例INT8 可能塞 16 个。这在横向扩容的时候能省不少机器成本做服务部署的同学应该懂这个价值。2. INT8 矩阵乘的硬件真相算得准靠的是累加器的高闲职要理解 INT8 矩阵乘为什么能保持精度必须看硬件内部怎么处理乘法结果。这一步搞懂了后面的校准思路就顺理成章。2.1 低精度计算高精度累加INT8 乘 INT8结果是 INT16 范围。但矩阵乘要做很多次乘加GPU 的 Tensor Core 和 CPU 的 SIMD 指令都采用INT8 乘法 INT32 累加的组合。也就是说每一次乘法误差范围有限累加的精度却保留得很宽。这带来一个很有意思的结论INT8 矩阵乘的误差源头主要在把浮点数变成 INT8这一步的舍入而不是矩阵乘本身。只要缩放系数选得合适、数值范围卡得准乘加过程的累积误差是完全可控的。2.2 量化公式就是线性映射标准做法是把浮点值按线性关系映射到整数域。对称量化symmetric——就是实际做推理时默认的基础。公式是q round(clamp(r / s, -127, 127))其中r是原始浮点值s是缩放因子q是量化后的整数。反量化就是r ≈ q * s。非对称量化asymmetric会多一个零点偏移 z公式变成q round(clamp(r / s z, 0, 255))非对称常用在激活值上因为激活一般不是正负均匀分布的。权重量化因为数值分布相对稳定对称量化居多。为什么最小都用 -127 而不是 -128细节在于 NVIDIA Tensor Core 有些 INT8 算子会把 -128 排除掉某些硬件上 -128 有特殊含义部署时如果算出的最小值恰好落在 -128 附近建议检查算子是否支持。2.3 量化的变形金刚GEMM 融合光有矩阵乘还不够真正提速要靠算子融合。实际推理时量化不是简单在每个算子前后加转换而是把量化和反量化吃进 GEMM 计算里。典型流程是这样的权重提前离线量化成 INT8上一层的输出如果已经是 INT8就直接进入 GEMMGEMM 输出的 INT32 累加值配合 weight scale 和 input scale 做一步反量化同时写入下一层的量化逻辑这一步合起来的公式大约是output_fp32 (accum_int32) * (scale_weight * scale_input)实际实现里往往再合并 bias变成单次乘加。我见过有些初学同学把量化算子逐个插入每一层导致每层都要从 FP32 转来转去速度不仅没提升反而变慢。关键是让 scale 的乘除和量化操作融合到主计算里而不是当独立算子跑。3. 校准Calibration量化误差的源头控制校准这一步直接决定量化后模型掉不掉点。很多人跑完量化发现模型傻了八成问题出在校准数据和校准方法上不是量化本身的锅。3.1 校准到底是什么量化的本质是找一组缩放系数把浮点张量映射到整数域。问题是同一层在不同输入下的激活值范围不一样不能等推理时再动态统计所以需要在量化前用一小批数据跑一遍模型统计出每一层激活值的分布然后挑一个合适的范围。这个过程叫校准calibration跑的数据叫校准集calibration set。校准集和训练集的关系有点像让模型做一次摸底考试用少量样本来判断每个激活值大概落在什么区间。3.2 四种常见校准方法的特点和坑方法原理适用场景容易踩的坑MinMax直接用 min/max 作为量化边界分布均匀的层极端值出现时边界被拉爆精度骤降Percentile百分位取 99.9% 或 99.99% 分位作为边界激活值有轻微异常值百分位选太大会回到 MinMax 问题KL 散度熵搜索使量化前后分布 KL 距离最小的边界TensorRT 默认方案CNN 上很稳校准集太少时结果不稳定MSE均方误差最小化量化前后激活值的均方误差精度敏感模型搜索粒度太大时可能跳过最优解TensorRT 成名的校准方式就是 KL 散度实质是让量化后的分布尽量贴近原始分布的信息量。这个方法对绝大部分 CNN 模型效果稳定我建议默认优先试。3.3 校准集选择最容易翻车的地方校准集的目的是覆盖真实推理时的数值分布不是为了刷准确率。我踩过的一个典型坑用训练集中的高质量样本做校准结果验证集偏真实场景掉点严重。后来发现训练集图片普遍明亮干净真实部署场景有很多暗光、模糊、遮挡的情况量化边界完全没覆盖。三类数据不能做校准集增强过度的数据旋转、裁剪、加噪幅度太大分布脱离真实场景单类别占比过高的数据比如只有猫没有狗激活通道分布失衡批量太小少于 100 张/条基本不够看我现在的习惯是从验证集里随机抽 500~2000 个样本确保覆盖各类标签和光照条件再跑 1~2 轮前向统计。样本数量不是多多益善超过 2000 张之后收益曲线基本上走了。3.4 校准后的验证只看准确率远远不够量化完不能只看 Top-1 准确率还要检查以下维度:类别的混淆矩阵有没有出现明显的系统偏移比如所有猫都被分到狗回归任务要看最大误差不能只看均方误差输出 logits 的分布和量化前是否大体一致延迟和吞吐有没有实际提升我遇到过一次量化后 Top-1 几乎不掉但某一类特定暗光场景下预测完全错误。后来查分布才发现这一类的激活和校准集分布偏差很大属于幸存者偏差。保险起见上线前一定要拿真实业务数据做一轮盲测。4. QAT训练感知量化精度救不回来时的王牌PTQ训练后量化跑完掉点超过 1~2%常见手段是校准集调大、换校准方法、对敏感层做混合精度。如果这些都试过还是不行就该上 QAT 了。4.1 QAT 的核心机制假装量化但梯度照常回传QAT 的做法是在训练过程里插入伪量化节点fake quantize前向直接把数值量化到低精度让模型看到量化后的损失反向传播时用一个直通估计器STEstraight-through estimator把量化函数的梯度近似成直通保证训练能正常收敛。公式理解起来很简单。前向q quantize(r)反向的梯度∂loss / ∂r ≈ ∂loss / ∂q原因在于量化函数 round 的导数几乎处处为 0不做 STE 的话梯度传不下去模型根本学不动。4.2 QAT 实操的通用套路先做 PTQ 得到一套较好的量化边界把它作为 QAT 的初始化在模型中插入伪量化节点PyTorch 里可用torch.quantization.quantize_fx的 Fx 模式或用torch.ao.quantization的 QAT 接口用比原始训练更小的学习率通常是原来的 1/10跑几个 epoch 让模型适应量化误差训练结束后移除伪量化节点导出真正的 INT8 模型关键点是QAT 不是重新训练。所需 epoch 通常不超过原始训练的 20%太多反而可能过拟合。4.3 QAT 对哪些模型特别有效分类网络ResNet、MobileNet 系列——QL 效果稳定检测网络YOLO、SSD——PTQ 掉点经常在 3% 以上QAT 能压回 1% 以内分割模型U-Net 这类——整体稳定但边界分割细节可能退化QAT 有帮助小模型MobileNetV3、EfficientNet-Lite——本身参数冗余少PTQ 经常难受QAT 基本是标配之前在一款边缘设备上部署 YOLOv5PTQ 直接掉 4 个点换成 QAT 跑 15 个 epoch掉点压回 0.8。代价只是多花了两小时训练时间换来的是模型上线后稳定运行。4.4 别上来就 QAT先跑一遍完整排查链路我建议的排查顺序是PTQ 默认配置 → 调整校准集 → 换 KL/MSE → 排查敏感层 → 混合精度 → 最后才 QAT。很多场景前三步就能解决直接上 QAT 属于用大炮打蚊子。顺便提一个经验值LayerNorm、Softmax、最后的分类头这类层对精度极度敏感量化时建议保持 FP32混合精度方案可以参考tensorrt的 per-channel 设置用 per-tensor 还是 per-channel 也值得实验对比。5. LLM 量化权重还好激活和 KV Cache 才是大头LLM 量化和 CNN 量化看起来都是 INT8实际难度的分布完全不同。我开始做 LLM 部署的时候踩了不少坑这里把要点拆开说。5.1 LLM 和 CNN 在量化上的本质差异CNN 的激活值一般相对平滑分布符合高斯之类的形态LLM 的激活值则经常出现少量极端大的 outlier出现在固定通道上。这些 outlier 会把量化范围拉得很大其他正常值量完精度惨不忍睹。这个问题在论文里被称为激活中的异常值问题。SmoothQuant 的思路就是把激活的 outlier 平滑掉一部分转移到权重上这样两边都好量化。权重方面也要提防LLM 里有个著名的海量特征维度现象——少数敏感通道对结果影响极大AWQ 的核心贡献就是保住这些敏感通道的权重。5.2 常见的几种 LLM 量化方案怎么选方案精度策略算力开销适用场景GPTQ仅权重量化按层做误差补偿低可用 4bit kernel追求极限压缩比可以配合 AWQ 使用AWQ仅权重量化保护敏感通道低和 GPTQ 类似压缩权重保持精度SmoothQuant权重激活 8bit 量化中等需要完整 W8A8 加速时KV Cache 量化对 KV Cache 做 8bit/4bit 压缩可忽略长上下文场景下必做实际部署时最常用的是 W8A16权重 8bit、激活 16bit或者 W4A16权重 4bit、激活 16bit。这两种方案只需要把权重换成低精度存储不需要额外的激活量化算子集成成本低。想要真正提升生成速度必须上 W8A8也就是权重和激活都量化。此时需要配套 SmoothQuant 这类技术处理比激活异常值否则精度损失在长上下文场景会迅速放大。5.3 KV Cache 量化是长上下文的必做课LLM 生成时每个 token 都要读一遍历史的 KV Cache上下文越长这部分开销越大。不做 KV 量化一个 32K 上下文请求可能比权重占用的显存还多。KV Cache 量化属于C 端收益不会体现在单 token 延迟上但能显著提升吞吐。量化方案通常是把 Key 和 Value 分别量化到 8bit 甚至 4bit精度下降在接受范围内配合 strong quantization 策略甚至可以超过不量化版本。我在 vLLM 上测过开启 KV Cache INT8 量化后相同显存下并发数提升接近一倍生成的 PPL 变化 0.1 以内。对长上下文场景这个优化几乎白捡。5.4 LLM 量化的实际回收效率量化位宽不是越低越好。4bit 权重的模型体积直降 75%但激活还是 16bit 甚至 32bit实际推理算力并没有全面加速只是显存和带宽压力变小。如果瓶颈在显存4bit 很合适如果瓶颈在算力W8A8 才是主赛道。举个例子在一张 3090 上跑 7B 模型FP16 权重占 14GB 显存INT8 占 7GB4bit 占 3.5GB。但如果激活仍 FP16单 token 生成速度基本不变只是能塞更多人并行。想真正提升单 token 速度必须做 W8A8 全量化。5.5 量化后 LLM 的幻觉风险这一条很多人忽视。量化会让模型对低概率 token 的预测更敏感可能改变模型在某些输入上的生成稳定度。我做 RAG 场景时碰到过量化后模型多次重复同一句或者突然开始输出和分析目标无关的内容。这个问题属分布外行为纯看 PPL 指标根本发现不了。我的处理方式是保留一个 FP16 原始模型做候选对比量化模型上线后前两周定期对比生成质量发现异常再回退或换量化策略。上线前的通用测试集建议加上对抗样本组比如诱导重复的提示语、指代混乱的句子、非常规的问题格式。6. 量化部署的通用流程与一些碎碎念最后给一个我在实际项目中反复使用的通用流程把上面所有内容串起来。这个流程从拿到模型到上线基本可以照抄。6.1 一套可以抄作业的流程预处理完成 BatchNorm 折叠把 BN 参数融合进前面卷积层否则量化边界会偏选择精度策略先用 PTQ INT8 跑一遍配合 KL 校准看掉点幅度校准集迭代如果掉点先检查校准集换数据源、加样本量重跑敏感层排查逐个把层设回 FP16 或 FP32找到掉点主要来源混合精度仅敏感层保持高精度其余层 INT8还是不行就 QAT按 4.2 套路初始化、微调、导出用真实业务数据做盲测检查混淆矩阵、生成稳定性、延迟分布上线后持续观测尤其注意异常输入下的表现6.2 工具链的选择PyTorch 自带量化工具适合研究和 QATONNX Runtime 的onnxruntime.quantization适合 CPU 部署TensorRT 适合 NVIDIA GPU 服务端RKNN Toolkit 适合瑞芯微边缘芯片vLLM 自带 GPTQ、AWQ、FP8 支持服务端 LLM 首选。工具不是越高级越好关键看你的部署目标平台。先看目标平台支持哪些量化格式再选工具顺序反了容易白干。6.3 量化不是银弹有些模型本身容量就很饱和量化会直接把边缘能力削掉。典型的例子是轻量化模型本身就已经压得很紧再量化等于二次伤害。这类场景我建议先考虑提升原始模型容量或蒸馏不要死磕量化。另一个建议是多做 AB 对比别急着把量化模型设为默认。尽量保住量化前版本和量化版本两套出口线上流量按百分百切随时能回滚。我个人实际部署的经验是先把校准集质量搞对大多数模型 PTQ 就够用QAT 不是默认选项是兜底手段LLM 量化优先看 Kv Cache 和 W8A8 支持权重位宽往 4bit 走前先确认带宽瓶颈在不在显存上。这一整套跑下来量化的收益基本能稳定吃掉剩下的是日常迭代时的细心活。
返回列表