很多第一次把大模型部署到本地的人都被同一道算术题劝退过一个7B模型用FP16存权重需要大概14GB显存再加激活值和KV Cache一张24GB的卡勉强能跑换成INT4之后权重只要3.5GB同样一张卡可以把上下文长度和并发拉高好几倍。这是大模型量化最直接的吸引力也是我最常被问到的起点。量化Quantization并不是什么新东西图像和语音推理里用了很多年但到了大模型这个尺度它从“可选优化”变成了“部署必修课”。这篇内容是对大模型量化技术的原理总结我会从底层数值逻辑讲到GPTQ、AWQ这些主流方案再结合我实际部署时踩过的坑把量化为什么有效、什么时候会失效、怎么选方案一次讲清楚。适合正在做推理部署、想在消费级显卡上跑模型或者想搞懂量化内部机制的同学。1. 为什么所有做推理的人都绕不开量化显存、带宽和成本的第一性原理1.1 模型参数与显存之间的换算关系先建立一个最基本的量化刻度模型显存占用 参数量 × 每个权重占用的字节数。一个70亿参数模型FP16是2字节所以权重部分是14GBINT8变成1字节权重部分缩到7GBINT4严格来说是0.5字节权重部分只要3.5GB。这个换算关系看着简单但绝大多数人第一次算账时都会忘记激活值和KV Cache的存在导致部署时爆显存。激活值对应前向传播过程中每一层的中间结果。推理时通常连续执行多层每一层的中间结果都要在显存里短暂驻留batch size一旦上去激活值的体积会和序列长度的平方级联动。KV Cache则是Transformer解码阶段为每个历史token保存的Key和Value向量用来避免重复计算上下文越长它膨胀得越快。这两块在长上下文场景下甚至能超过权重本身。所以评判一次量化收益时我习惯把三部分拆开看量化的直接受益方是权重文件KV Cache需要单独量化和缓存管理策略激活值量化则主要影响计算加速而不是显存占用。1.2 访存带宽才是推理速度的真正瓶颈很多人以为量化只是省显存实际上它对推理速度的影响往往更大。大模型生成是典型的访存密集型过程每生成一个token都要把模型全部权重从显存读一遍参与计算。这时候吞吐量取决于显存带宽除以权重体积。一个7B FP16模型权重是14GB消费级显卡带宽大约500GB/s到1TB/s单次完整读取就要十几到二十几毫秒。换成INT4之后权重变成3.5GB同样带宽下读取时间压缩到原来的四分之一token生成速度自然提升。这也是为什么同一个模型在不同位宽下推理速度差异会如此明显。如果只是算力瓶颈量化带来的计算加速远没有这么显著。理解这一点对优化很有用当你发现量化后速度提升有限往往不是量化本身的问题而是序列长度较长时KV Cache访存成了主导这时候单纯压缩权重收益就不大了。所以很多推理框架会专门把KV Cache做量化或分页管理本质上都是在降低访存总量。1.3 量化的本质在精度与资源之间做交易把精度当成一种可以主动放弃的资源这是量化思维和传统数值计算思维最大的不同。浮点数世界里每个数值都有精细的分辨率但神经网络特性决定了它对大多数参数的微小扰动并不敏感。一个权重从0.123456变成0.12对最终输出的影响可能小到可以忽略。量化要做的事情就是找到这个“可以忽略”的边界把连续取值空间压缩到有限个离散点上用更少的bit表达同等程度的有效信息。这个交易是否划算取决于三个变量模型对扰动的容忍度、量化方法对误差的分配方式、以及硬件对低精度计算的支持程度。不同模型对量化的敏感度差异极大有的模型INT4做完几乎不掉点有的模型连INT8都会出现明显退化。这种差异性不是玄学而是来源于权重分布和激活值分布的特征后文会深入展开。2. 量化背后的数学基础从浮点数到整数的信息取舍逻辑2.1 FP16、BF16和FP32在数值表示上的差异量化原理要从浮点格式讲起。FP32由1位符号、8位指数和23位尾数组成动态范围极大能表示的数值从极小的科学计数到3.4e38都能覆盖。FP16把指数位压到5位、尾数压到10位范围明显缩小精度也下降但好处是体积减半。BF16是另一个方向保留8位指数、只留7位尾数所以它和FP32的动态范围几乎一致但尾数精度很差。很多刚接触大模型的人会疑惑训练时经常用BF16推理时为什么偏好FP16因为BF16的动态范围适合训练中防止梯度溢出但尾数精度不足会导致推理阶段对激活值的表示不够细腻。而FP16在小数值区间精度更高。这项差异在选择量化方案的缩放策略时有实际意义比如某些硬件上BF16与FP16对量化后数值的支持度不一样直接影响可选的量化格式。2.2 对称量化与非对称量化量化公式的起点是线性映射。给一组浮点数值我们希望把它映射到整数范围对称量化用INT8的[-127,127]非对称量化用UINT8的[0,255]或者INT8全范围配合零点。对称量化假设数据分布关于0对称所以只求一个缩放因子scale反量化公式是 r scale × q。非对称量化则额外引入零点zero point公式变成 r scale × (q - zero_point)。对于权重来说训练后的权重分布大体接近零均值对称量化效果通常不错实现也更简单。激活值则不同特别是经过ReLU或SiLU之后激活值常常整体偏向正值、呈现出明显的偏态分布这时候非对称量化能显著减少量化误差。这也是很多量化框架对权重用对称、对激活用非对称的原因。不过非对称量化需要多算一个零点偏移计算和硬件支持都有额外成本有些芯片的INT8指令不支持非对称落地时得看算子库的实力。2.3 缩放因子、零点与反量化过程把量化拆成端到端流程来看前向传播中浮点张量需要经过“统计范围 计算scale/zero_point 四舍五入取整”才能变成整数张量送入计算算子之后整数结果还要经过反量化变回浮点数值传给下一层。这里最容易忽略的是取整误差。四舍五入本身是确定性操作但当数值离最近的整数点较远时舍入误差会累积。量化方案的核心优化目标就是如何降低这一步的信息损失。一个直观类比是把一张高清照片从1600万色压缩到256色scale相当于定义调色板的整体范围零点相当于调色板的偏移量而取整就是查找离每个像素最近的调色板条目。如果调色板范围选得太宽低亮度区域的细小差别全被抹平选得太窄高光区域直接爆掉变成纯白。大模型量化里对应的问题就是范围裁剪和离群值处理。2.4 校准集与分布裁剪min/max和百分位法的区别量化范围怎么确定是整个流程里最容易被低估的环节。直接取张量的全局最小值和最大值看似最完整但如果分布里存在少数离群值整个scale会被这些异常点拉大导致绝大多数正常数值被迫挤进更粗的量化步长里。我见过有人对激活值直接min/max量化后一个本来正常的模型困惑度飙到天际原因就是个别激活值大得离谱。工程上更常用的做法是用部分有代表性的数据做校准calibration观察权重或激活值的真实分布然后按百分位裁剪。比如取99.99%分位数作为最大值自动忽略极端离群点。百分位选多少要拿捏裁剪太多会引入截断误差裁剪太少又会被离群点拖累。此外还有基于KLD散度的方案在信息损失的意义上寻找最优裁剪点TensorRT的INT8量化就用类似的思路。校准集的选择同样关键必须覆盖真实使用场景的输入分布否则统计出来的scale在线上会遇到“域偏移”。3. 主流量化方案的原理与差异从PTQ到GPTQ再到AWQ3.1 训练后量化PTQ为什么是最先落地的路线训练后量化Post-Training QuantizationPTQ最容易理解模型已经训完你只需要找一小批校准数据统计数值范围然后把权重和激活从FP16转成低精度即可。整个过程不需要反向传播只需要前向推理通常几分钟就能完成。对于已经投入大量成本训练好的模型这是最省事的落地方式。PTQ的局限也很明显它本质上是一个“事后补救”式的近似优化。量化误差在每一层产生后会逐层传播前几层的误差会被后续层放大尤其是激活值中含离群值时PTQ的鲁棒性很差。实践中PTQ适合8bit量化放到4bit通常衰减明显除非使用更复杂的量化策略。很多“一行代码量化模型”的工具默认做的都是这种但你要清楚它并不附加任何对误差的再分配能力。3.2 GPTQ的思路用二阶信息补偿舍入误差GPTQ是目前INT4权重量化最有影响力的方法之一。它的思想继承了经典的OBSOptimal Brain Surgeon框架逐层对权重做量化每量化一个值之后用该层损失的Hessian矩阵来估计这个舍入误差对其他权重的影响然后对尚未量化的权重做一次校正更新。直观来说它不只是“选一个最近的整数”而是让整个层的权重共同分担这一小步的精度损失最终让该层输出的误差在整体上最小化。实现上的关键点是层的Hessian矩阵和分批更新的求解方式。对大模型来说直接计算所有权重的二阶信息代价太高GPTQ通过Cholesky分解和分块更新的方式把它控制在可接受的计算范围内。实际操作中GPTQ需要设定group size常见128也就是每128个权重共享一组scale和zero point这相当于在精度和存储开销之间做平衡。用AutoGPTQ做4bit量化时我非常建议至少准备几百条和真实任务同分布的校准文本而不是随便找一段长文本充数。3.3 AWQ的思路按激活值重要性保护敏感通道AWQActivation-aware Weight Quantization采用了和GPTQ完全不同的切入点。它观察到模型权重里存在一小部分“重要通道”这些通道对应的激活值幅度显著高于平均水平而且对模型输出质量起决定性作用。传统量化一视同仁地处理所有权重导致这些关键通道在低bit下损失惨重。AWQ的思路是给这些重要通道施加更高的量化保护但又不是额外分配高bit位宽而是通过一个按通道的缩放因子在量化之前先把重要通道的数值范围“撑大”使它们经过量化后保留更多有效信息。这个缩放操作不需要反向传播只需要少量校准数据统计激活值幅值。相比GPTQ的逐层二次优化AWQ的过程更轻量实测中在部分模型上比GPTQ更稳尤其在4bit场景下经常能保住更多指令跟随和推理能力。AutoAWQ也是我目前做低bit部署时最常用的工具之一。3.4 QAT与量化感知微调QLoRA什么时候才值得用PTQ和GPTQ/AWQ都属于训练后方案而量化感知训练Quantization-Aware TrainingQAT是在训练或微调阶段就模拟量化噪声。它通过插入伪量化节点让模型在参数更新时就适应离散化误差从而获得更高的量化后精度。QAT开销大需要完整训练流程所以主要用在最优PTQ仍然不达标、或新架构模型对量化极度敏感的场合。QLoRA则代表了另一种潮流的结合方式主模型冻结后以4bit NF4格式加载只训练注入的LoRA低秩适配器。这里4bit不是用于最终部署的而是为了在有限显存里跑更大的模型做微调。NF4Normal Float4是一种针对权重分布设计的分位数量化格式信息密度比普通INT4更高特别适合作为训练时的冻结存储格式。训练完成后把LoRA适配器合并回去可以再导出成自己需要的推理位宽。这解决了“没有足够显存微调大模型”的经典困境也让我在消费级显卡上微调7B模型变成了常态。4. 位宽、粒度和混合精度决定量化质量的关键工程参数4.1 INT8、INT4、FP8、NF4各适合什么场景不同数据格式各有对应的主流战场格式关键特点典型场景INT8精度损失小、硬件支持最广泛、算子生态成熟服务端部署、TensorRT、部分边缘设备INT4显存减半减半再减半但需要GPTQ/AWQ级算法校准消费级显卡、长上下文、高并发推理FP8动态范围优于INT8但依赖较新硬件Hopper及之后架构的训练和推理NF4分位数映射4bit信息密度高QLoRA训练时冻结模型存储格式INT8最大的优势是兼容性好几乎所有主流GPU和推理框架都对INT8算子做了深度优化量化后精度衰减通常小于1%。INT4则必须面对一个现实精度退化不再是线性的算法选择和校准质量的影响会被放大。FP8目前在训练侧应用更多推理侧算子支持还在完善中但它解决了INT8动态范围不足导致的大激活值溢出问题。NF4一般不直接作为部署目标格式更多是训练中间格式。4bit家族里还有GGUF格式的Q4_K_M、Q4_K_S等变体它们来自llama.cpp生态的k-quant方案。这些格式不是单一算法而是在per-channel和per-group之间做了启发式混合对CPU推理场景做了针对性优化。如果你是在纯CPU机器上跑大模型这些格式往往是性价比最好的选择。4.2 量化粒度张量级、通道级和分组级如何取舍量化粒度决定了scale和zero point的共享范围范围越大开销越小、误差越大范围越小精度越高、元数据越多。按一张权重矩阵来说per-tensor是整张矩阵一个scale实现最简单但对通道间数值差异大的模型衰减严重per-channel是每个输出通道一个scale精度大幅提升也是8bit量化的常见默认选择per-group则是把通道内元素再分块比如128个元素一组共享一组参数是4bit量化保持精度的关键手段。我通常的选型经验是8bit用per-channel足够4bit必须配合group size 128特殊情况降到64。group size减小会带来两个副作用一是存储scale的额外开销增加二是量化时的查找和计算变复杂推理框架的解码效率会受影响。不要盲目追求小group先看评测指标是否真的提升再看实际生成速度是否被拖累。另外近年来部分框架支持activation的per-head粒度这种细腻化的趋势主要服务于KV Cache量化场景。4.3 KV Cache量化为什么经常被单独拿出来做在长上下文场景下KV Cache往往成为显存瓶颈。它的体积可以粗略估算为2K和V × 层数 × KV头数 × 头维度 × 序列长度 × batch大小 × 每元素字节数。这个公式意味着序列长度和并发每上涨一点KV Cache就会快速增长。拿一个32层、8个KV头、头维度128的模型来说4K上下文、batch为8时FP16的KV Cache就可能占据2GB以上显存。KV Cache量化通常采用INT8或FP8因为它对精度极其敏感直接上INT4容易在长文本生成时出现重复、中断等质量问题。量化KV Cache时建议保持per-head粒度因为不同注意力头之间数值分布差异明显全局scale会牺牲注意力计算的整体准确性。另外KV Cache量化在解码过程中反复执行量化和反量化推理框架需要对这部分算子做专门优化否则节省的显存会被计算开销抵消。4.4 混合量化敏感层保持高精度的实操手法不是所有层对量化的敏感度都一样。我做过一个实验把同一个模型的不同层分别量化成INT4其余保持FP16结果发现部分层的退化幅度是其他层的数倍。典型的高敏感区域包括靠近输出的层、MLP中放大因子的相关层以及某些对数值范围要求特别高的Attention投影层。混合量化的实操思路很简单先全量量化用评测集跑分再逐步把敏感层恢复成高bit或FP16观察分数变化。这个过程最好用脚本自动化完成不要手动一层层试。框架层面部分现代推理引擎允许指定层级的量化精度的override配置这也让混合量化从学术研究走向了工程可用。不过混合量化会牺牲一部分存储连续性和算子融合优化显存节省会被打折所以要衡量到底是显存更紧缺还是精度更紧缺。5. 实操选型结合工具链与硬件的量化落地建议5.1 不同生态的量化工具链怎么选量化工具的选择要先看部署目标再谈哪个框架好用顺序反了会吃大亏。场景推荐工具链理由英伟达GPU服务端高吞吐TensorRT-LLM、vLLM AWQ/GPTQ算子优化深、支持批量推理、流水线成熟消费级单卡、本地部署AutoAWQ vLLM或ExLlamaV2易于尝试不同位宽调试显存方便CPU或苹果芯片llama.cpp GGUF对异构硬件做了针对性优化极致降低部署门槛快速原型验证transformers bitsandbytes几行代码就能加载4bit模型但性能不是最优微调后导出QLoRA 合并导出任意格式解决显存不够训练的问题同一模型在不同工具链下的量化后精度可能不同因为校准策略、算子实现和数值细节都有差异。我的习惯是至少准备两套方案先用bitsandbytes快速看4bit能不能跑、精度损失量级多大如果可行再切到AutoAWQ/GPTQ做正式量化并评测如果目标是CPU部署直接从头看llama.cpp的GGUF支持列表更高效。5.2 评估量化效果时要看哪些指标评估量化效果不能只看一个指标。Perplexity困惑度是最常用的粗筛指标它能快速反映模型整体概率分布的偏移但不够精确有些量化模型ppl看似漂亮实际指令理解或者数学推理已经崩了。更可信的做法是跑一个组合评测集比如常识推理MMLU、数学GSM8K、代码HumanEval和若干中文任务同时对比原始FP16模型的基线。评估时还要注意几个隐藏变量生成参数不一致会导致结果波动比如temperature和top_p不同max_new_tokens应该固定同一题目多次采样最好取多次结果平均因为解码的随机性可能掩盖量化带来的退化。另外随机种子对部分评估集也有影响跑分前先把种子固定。如果你做的是私域数据微调模型不要只跑公共集直接抽一批真实业务case做人工比对答案格式变化往往比分数更能反映问题。5.3 从INT8到INT4实操中的常见衰减模式与应对我在实际部署中总结了几类最常见的量化衰减模式基本每个做过低bit部署的人都会遇到。第一类是数学推理大幅退化典型表现是GSM8K分数掉5到10个点。这通常意味着关键权重被过度压缩可以尝试改用AWQ、减小group size到64或者对特定层实施混合量化。第二类是长文本生成出现重复和死循环这常常和KV Cache量化有关优先检查是不是KV Cache也上了低bit把它恢复到INT8或FP16。第三类是指令遵循能力变差模型能听懂话但执行步骤丢失。这种情况可能是校准集偏了导致激活值分布估计不准。我踩过的一个典型坑是用英文通用语料做校准结果部署中文业务指令时明显衰退。后来改用混合中英文、贴近真实业务的校准集效果立刻改善。校准集不是越多越好但必须是“领域相关且有代表性”的。写在最后的实操体会我在推动量化落地时有一个习惯不要一上来直接追求最低bit而是先明确资源瓶颈在权重、KV Cache还是部署环境。如果是权重瓶颈优先考虑AWQ或GPTQ加混合精度如果是长上下文瓶颈先量化KV Cache而不是盲目压权重位宽。另一个经验是量化方案的选择和模型来源关系很大同一个模型的不同量化版GGUF、AWQ、GPTQ表现各异下载模型时优先选择专门做过校准和评测的社区量化版本能少踩很多坑。我自己经历过无数次“量化完跑分挺正常一上业务就露馅”的翻车现场慢慢总结出最稳妥的路径小步验证、多指标评估、分层恢复。量化从来不是把bit数调低那么简单它是对模型数值特征的体检也是部署工程的耐心活。
阅读完成 · 觉得有帮助?