资讯动态

大模型量化实战:从FP16到INT8/4-bit的显存与速度优化

发布时间:2026/10/20 3:13:50 来源:尧图企业网站定制
先从一个最实际的痛点说起。你手里有一个跑得很好的大模型部署到本地后显存告急、推理速度感人每生成一个 token 都要等半天。很多人第一反应是换一张更大的卡但真正花钱少、见效快的思路是给模型做一次量化手术——把权重从 FP16 换成 INT8 甚至 4-bit体积直接砍到四分之一速度却有肉眼可见的翻倍提升。这篇是这个系列里我个人最偏爱的一篇因为“模型量化”是少数几个理论门槛不高、收益又极其直观的优化手段不需要重新训练不需要改动网络结构只需要把数字的“存储精度”降低就能换来实打实的部署红利。适合正在做本地部署、边缘推理或者单纯被显存逼到墙角的朋友参考。需要提前说清楚的是量化不是玄学也不是简单的“四舍五入”。它背后有一整套误差控制逻辑该保留哪些信息、该牺牲哪些精度、按什么比例去分配那几个比特位都是有讲究的。这篇文章我会从量化最基本的映射关系讲起然后一步步走向 INT8 的经典流程再拆解冲到 4-bit 时用到的几个关键思路最后用一组实测数据复盘收益和踩过的坑。1. 为什么模型越跑越慢算力墙面前的一次手术先聊一个反常识的事实大模型推理的瓶颈往往不是计算而是显存带宽。以自回归生成为例模型每生成一个新的 token都要把全部权重从显存搬到计算核心里做一遍乘加运算。权重不会变但每次生成都要重新读一遍。如果你的模型有 70 亿参数FP16 精度下光权重就是 14GB假设你的显卡带宽是 500GB/s那么每生成一个 token光读权重就要花 28ms 左右。你可以把 GPU 想象成一个仓库和加工车间的关系加工车间算得再快仓库送货的速度跟不上整体产量也上不去。量化做的不是让车间更卖力而是让“每趟货”变轻——原来每次搬两字节现在搬一字节甚至半字节同样的时间能读两倍甚至四倍的权重内容解码速度自然明显提升。这也是为什么量化能在几乎不动计算量的情况下带来接近翻倍的速度收益。再算一笔体积账FP32 是 4 字节FP16 是 2 字节INT8 是 1 字节INT4 只有 0.5 字节。同一个模型精度单权重占用70 亿参数权重体积相对 FP16 体积FP324 字节28GB200%FP162 字节14GB100%INT81 字节7GB50%INT40.5 字节3.5GB25%所以“极限压缩”指的是把模型权重从 FP16 一路压到 4-bit体积只剩原来的四分之一。原来一张 24GB 的卡勉强放下 FP16 模型量化到 INT8 后 12GB 卡就能跑再压到 INT4 后 8GB 卡都有富余。这就是量化最直接的红利降低显存门槛。1.1 量化不是“压缩文件”而是真正换了数据类型初学者最容易混淆的是量化与打包压缩的区别。ZIP 或 RAR 压缩文件解压之后数据还是原来的数据精度一分不差量化则不同它是把每一个浮点数强行放进一个精度更低、值域更窄的整数格式里。一旦转换信息就有损失不可逆。可以这样理解FP16 能在很大范围内表达非常精细的小数比如 0.33333334、-3.1415927 这类INT8 只有 256 个档位可以放数字INT4 更夸张只有 16 个档位。量化做的就是把这 256 个、16 个档位安放在最合适的位置上让真实值尽量落在这些档位附近并把误差控制到尽量小。所以量化的本质是一个“信息重新编码”的过程而不是一个“无损打包”的过程。1.2 为什么位宽越低跑得越快大模型推理还有一个特点是权重在显存里“躺着不动”但每一层计算都要“一遍遍读它”。位宽越低每次搬运的数据量越少。比如同样读 14GB 的权重FP16 需要搬 14GBINT8 只需要搬 7GBINT4 只需要搬 3.5GB在显存带宽不变的前提下单纯数据搬运时间就能减少一半甚至七成而矩阵乘加的整数计算在现代硬件上并不比浮点慢多少。所以“性能翻倍”并不是夸大其词——在很多典型场景下FP16 换成 INT8 后推理吞吐量能到原来的 1.7~1.9 倍换成 4-bit 后还能再高一点。前提是你得把量化的误差控制住否则表面上是变快了实际生成的内容已经开始胡说八道。这一节讲清楚了量化“为什么要做”和“为什么有效”下一节进入正题看看这些数字到底是怎么被“削”下来的。2. 量化手术的解剖学那些数字是怎么被“削”下来的如果你想理解后面所有高级量化技巧只需要抓住一件事量化就是找一个映射关系把浮点数范围映射到整数范围再用这个映射关系反解出近似值。2.1 映射公式真正的“存数字”方式简化形式如下。假设一组浮点权重的最小值是 a最大值是 b你要把它们映射到 0 到 255INT8或 0 到 15INT4的整数区间里那么先算出缩放系数和零点scale (b - a) / (q_max - q_min) zero_point round(q_min - a / scale)正向量化q round(fp / scale) zero_point反量化重建fp_approx (q - zero_point) * scale这个映射就是量化的全部核心。int4 的 q_min 是 0q_max 是 15一共 16 个档位int8 的 q_min 是 0q_max 是 255一共 256 个档位。scale 决定了每个整数档位对应的浮点“步长”zero_point 决定了零点落在哪个整数档位。举个例子有一组权重分布在 [-2.0, 2.0]量化到 INT8 后scale (2.0 - (-2.0)) / 255 ≈ 0.0157。也就是说每个整数档位之间隔了 0.0157原来 4.0 的量程被分成了 256 格。量化后的数字再反解回来误差通常在半个档位以内即 0.0078 左右。这个误差对神经网络来说通常是可以接受的因为单个权重的微小偏差会被几百上千个权重平均掉网络整体输出不会偏离太多。2.2 对称量化与零点什么时候该用哪种实际工程里有两种主流量化格式对称量化和非对称量化。对称量化把浮点范围看成关于 0 对称的即min -max这时 zero_point 恒为 0公式可以简化成q round(fp / scale)。它的优势是推理实现非常干净整数矩阵乘不需要额外修正 zero_point 的偏移代价是如果实际权重分布是不对称的很多模型的权重分布确实不是完全对称会造成一定的范围浪费。非对称量化则单独记录 min 和 max用 zero_point 对齐零点。它更适合激活值这类分布很不均匀的浮点数据因为可以精确覆盖真实范围不浪费档位缺点是部署复杂一些需要在整数乘加后额外处理 zero_point 的偏移项。我的建议是权重一般用对称量化激活值一般用非对称量化。这是目前大量开源推理框架里的默认做法也是实践下来表现最稳的组合。2.3 校准数据与动态范围量化精度的第一块基石真正决定量化误差上限的往往不是位宽而是动态范围的估算是否准确。同一个权重张量如果 min 和 max 估大了step 变粗档位浪费误差变大如果估小了很多真实值溢出直接截断误差更大。所以量化前的“校准”环节非常关键。做法是拿一小批有代表性的输入数据前向跑一遍模型统计每个权重张量、每个激活张量的实际 min 和 max、甚至更细致的分布直方图。然后根据这些统计结果去确定 scale 和 zero_point。校准数据要满足两个条件一是数量不用太多几百条典型样本往往就够二是必须覆盖模型上线后会遇到的数据分布不能拿训练集数据去校准那样会过拟合到训练分布的“舒适区”换个场景立刻暴露问题。这个坑我在第 6 节还会展开说。3. 实操第一步FP16 到 INT8 的后训练量化全流程如果你只是想把模型快点部署上线最实用的路径是后训练量化PTQ模型训练完不动权重只做一次前向校准然后把权重换成低精度格式。这套流程在多数开源量化工具里都已经封装得很成熟但了解每一步的原理仍然有用因为出了问题你能知道该去调哪里。3.1 PTQ 与 QAT 的取舍量化有两种主流路线PTQPost-Training Quantization训练之后做量化不需要反向传播速度快几分钟到几十分钟完成缺点是在极低位宽如 4-bit下精度损失可能明显。QATQuantization-Aware Training训练过程中就模拟量化误差让模型在训练时适应低精度表示效果更好但需要重新训练成本高。对大多数推理优化场景我的建议是先做 PTQ。如果 PTQ 之后精度崩了再考虑对敏感层做混合精度或者上 QAT。直接上 QAT 相当于为了省油把发动机整个拆了重装收益可能多几个点成本却高一个量级。3.2 六步完成 PTQ 量化一套完整的 PTQ 流程大致如下准备模型先把 FP16 权重导出固定 BatchNorm 等层确保模型处于推理模式。准备校准集收集 128~512 条代表性样本建议从真实业务数据里采样避免只用公开测试集。统计动态范围前向跑模型逐层记录权重和激活的 min、max、分布直方图。计算量化参数根据统计结果计算每层或每通道的 scale 和 zero_point。常用策略包括按张量整体统计per-tensor和按通道分别统计per-channel。通道级量化通常精度更好因为每个卷积核或注意力头的动态范围差异会被单独照顾。执行量化并评估把 FP16 权重替换成 INT8跑一遍完整的前向推理对比量化前后的困惑度和下游任务指标。导出部署把量化后的权重、scale、zero_point 一起打包接入推理框架。伪代码大致长这样# 简化的逐张量对称量化流程 import numpy as np def symmetric_quantize(fp_tensor, bits8): q_min 0 q_max (1 bits) - 1 max_abs np.abs(fp_tensor).max() scale max_abs / (q_max / 2) # 对称假设 q np.round(fp_tensor / scale).astype(np.int8) return q, scale def symmetric_dequantize(q_tensor, scale): return q_tensor.astype(np.float16) * scale # 使用示例 weight np.random.randn(4096, 4096).astype(np.float16) q_weight, scale symmetric_quantize(weight, bits8) weight_approx symmetric_dequantize(q_weight, scale) err np.abs(weight - weight_approx).mean()这段代码只是演示核心映射关系生产环境里还要处理 per-channel、非对称、校准集统计、溢出保护等一堆细节。拿开源工具链改一改配置就能跑但你理解了这段逻辑后至少不会把 scale 算错。3.3 量化后的精度评估别只看困惑度很多人量化之后只看一个困惑度PPL数值觉得 PPL 没涨多少就认为万事大吉了。实际上 PPL 是一个很宏观的指标它反映模型对下一个 token 的平均惊讶程度但无法反映具体任务上的细粒度差异。比如一个模型 PPL 只上涨了 0.3看似人畜无害但在代码生成任务上可能多出好几个语法错误在数学推理上多错一两道题。我建议做三件评估PPL 对比作为第一道筛子PPL 暴涨说明量化方案彻底失败。任务指标回归拿和上线场景一致的任务集跑量化前后各一次对比准确率、合格率、F1 等。人工抽样随机生成几十条输出肉眼判断质量是否退化。这个步骤听着土却是最能发现隐藏问题的。4. 冲击 4-bit精度几乎无损的三种独门手法INT8 相对容易因为 256 个档位对大多数权重张量来说已经够用了。但想压到 4-bit只有 16 个档位直接套用最简单的映射思路精度基本必崩。冲到 4-bit 还能保持精度靠的是下面这几个更聪明的补偿机制。4.1 暴力舍入为什么不行如果你把每个权重单独近似到最近的整数档位单个权重误差虽然只有 scale 的一半但当整个层有上百万个参数时误差会累积成一个不可忽略的扰动。尤其某些权重对最终输出的影响远大于其他权重一刀切的舍入根本没有区分“关键参数”和“普通参数”精度自然快速劣化。所以 4-bit 量化的核心思路从“每个数如何表示”升级成了“误差如何重新分配”。4.2 用损失函数的“二阶导数”做手术第一种思路来源于“最优脑手术”的经典思想既然某些权重可以被安全删掉那说明权重之间存在冗余那么量化掉一部分参数后可以通过微调其他参数来补偿损失。具体做法是逐层处理构建这一层输出对权重变化的敏感性矩阵Hessian 矩阵量化一个权重后立刻更新同一层其他未量化的权重让该层输出误差尽量小。这个过程像外科手术一样“切一刀补一刀”量化后的层在反向重建时几乎看不出原始输出的差异。因为变换是基于二阶信息对数值敏感度的判断比单纯看绝对值靠谱得多所以它能在 4-bit 下保住大部分精度。代价是计算开销比较大需要对每个参数算敏感度并不断更新补偿所以这类量化通常离线做一次量化可能需要几十分钟到几小时。4.3 把误差留给不重要的权重第二种思路更轻量也更适合快速部署不追求全局最优补偿而是根据激活值的分布找出哪些通道是“重要通道”。直觉是这样的权重和激活是配对使用的一个权重通道对应的激活值如果普遍偏大说明这个通道对输出的贡献大量化误差会被放大反之如果激活值普遍很小那这个通道的权重就算量化得粗糙一点影响也有限。所以操作方案是校准阶段统计每个通道激活值的平均幅度给激活幅度大的通道对应的权重施加一个保护系数在计算量化 scale 时让这些重要通道获得更细的档位。这种方法不用算二阶矩阵速度比第一种快不少精度却能非常接近。它给整个 4-bit 社区带来的最大启发是量化参数不一定要全局统一按“重要性”分配比特资源效果远好于平均分配。4.4 激活值也能帮忙平滑与分位数量化还有两条思路值得一提。第一条叫“平滑量化”。它发现有些模型激活值里会出现个别特别大的“离群点”这些离群点会直接把动态范围撑大导致普通数值分配到的档位变粗。解决方案是在量化前把一部分激活的“数值负担”转移到权重里预先算好一个平滑系数让激活值变得更平整同时权重值相应放大。这样激活量化容易了权重量化虽然变难一点但权重量化本身精度敏感度低整体是赚的。第二条是分位数量化。传统的均匀量化是等间隔切档位但神经网络权重的分布往往不是均匀的而是中间密、两边疏。分位数量化按数据分布的实际分位数决定档位边界让密度高的区间获得更多档位信息密度最大。4-bit 场景下常用的 NF4 就是这种思路假设权重大致服从正态分布按正态分布的分位点划分 16 个档位让多数权重落在更精细的区间。经验上它对大模型的激活和权重都友善是实现“低精度高保真”的重要基石。综合使用这些手段4-bit 量化已经可以在相当多的任务上做到“肉眼不可见”的精度损失。但注意这些方案比 INT8 的通用映射要复杂得多对硬件指令集也有额外要求不是所有推理框架都能丝滑支持选型时需要结合自己的部署目标权衡。5. 术后复查显存、速度、精度的真实数据对比光讲原理难免心里没底直接上数据。我以某个 70 亿参数的 decoder 模型为例子这几年的主流开源大模型基本都是这个规模在相同硬件上做了一组对比。场景是单卡推理输出 1024 个 token 的文本生成任务没有启用任何投机采样之类的花活。精度权重体积实际峰值显存解码速度相对 FP16任务准确率相对 FP16FP1614GB约 19GB1.0x基线INT87GB约 10GB1.7~1.9x下降 0.2% 左右INT43.5GB约 6GB2.0~2.2x下降 1%~3%因任务而异这组数据说明两个事实第一INT8 是性价比最高的一档。显存减半、速度接近翻倍、精度几乎无损对于绝大多数部署场景INT8 应当是第一选择。第二4-bit 的性能收益比 INT8 更高但存在精度悬崖。有些任务上 4-bit 的准确率只是从 92% 掉到 91%完全无感有些任务却可能从 80% 掉到 72%直接不可用。5.1 性能翻倍背后的硬件原因为什么 INT8 到 4-bit 的速度提升没有像“位宽再减半”那样也减半因为推理性能不是只受权重复制影响还有算子实现、访存模式、内存碎片、反量化开销等一堆因素。位宽越低单比特的收益边际递减。但整体 2 倍以上的提升仍然是实打实的这已经足够让很多单卡部署方案从“勉强能跑”变成“流畅生产”。5.2 什么任务经得住 4-bit什么任务经不住按照我的实测经验这几类任务对 4-bit 比较耐受文本摘要、情感分类、信息抽取、通用对话。这些任务输出通常有较多冗余模型有能力在低精度下“蒙”对重点。这几类任务则非常敏感数学推理、多轮精确指令执行、复杂代码生成、结构化输出比如严格的 JSON 格式。原因也好理解这类任务对数值细节要求极高每一步都需要精确计算一个 token 的微小偏差会沿链路放大最终输出完全跑偏。所以我的建议是别只看模型整体精度指标先跑一遍你要上线的那个具体任务用你自己的测试集说话。6. 4-bit 到底有没有上限我踩过的坑和判断标准最后聊聊我实际踩过的坑以及“什么时候该收手”的判断标准。6.1 校准集与线上数据分布不一致量化后直接“偏”我第一次做 4-bit 量化时拿了一批公开测试集做校准PPL 涨得非常小一度以为成了。结果部署到线上之后用户输入和测试集分布差得很远模型输出质量肉眼可见地下滑尤其是对长文本的处理明显不如 FP16。排查到最后发现问题出在校准数据没有覆盖线上场景的关键格式导致激活的动态范围估算偏了很多真实输入落到了容易被截断的区域。后来我的习惯是每次做量化前先线上采集 200 条真实样本人工检查一遍确保覆盖各种输入形态再用这些数据做校准。这一步看似花时间却能省掉后面无数排查工作。6.2 先量化还是先微调顺序错了损失翻倍另一个容易搞反的是想“先微调再量化”还是“先量化再微调”。如果你计划在量化后的 4-bit 模型上继续微调顺序很有讲究。直接对量化后的稀疏权重重跑常规微调量化误差会随着梯度更新被放大训完精度反而可能更差。常见的正确做法是使用“伪量化”机制在训练阶段前向计算模拟量化误差先量化再反量化反向传播时保留浮点梯度和浮点权重让模型逐步学会在低精度表示下寻找更优解。一句话总结量化微调要把误差模拟放在前向里而不是真的把权重改成 int4 再训否则就是在误差地板上跳舞。6.3 2-bit 是硬边界还是软边界理论上 2-bit 可以让 70 亿参数模型的权重体积降到 1.75GB非常诱人。但以目前的实践来看常规任务下 2-bit 的精度损失基本不可接受即使加了复杂的误差补偿也只是从“完全不能用”变成“勉强能展示”。我个人认为当前工程上稳妥的最低线就是 4-bit2-bit 更适合学术研究而不是投产。如果你被显存逼到必须用 2-bit优先考虑的不是更激进的量化方案而是换一个参数量小一点的模型效果通常更好。我的习惯做法是上线前做一条流水线——先用 INT8 保底部署再跑 4-bit 对比测试挑出敏感层保留 FP16通常是把 Embedding 层和最后的输出层留在高精度最后才决定全局用哪种方案。这个顺序能最大程度避免“一把梭 4-bit 全员翻车”的情况。结语最后再分享一个小技巧关于是否要把所有层都量到 4-bit我一直坚持的观点是除非显存真的就差那几百 MB否则没有必要追求全员 4-bit。混合精度往往是性价比最高的形态——Embedding、输出头、以及你测试下来误差最大的两三个层保持 FP16其余层量化到 INT8 或 4-bit既保住了精度底线又能把显存压到目标范围。用这个思路我多次把一些“看起来只能上 FP16”的模型成功塞进了小卡里而且线上表现差异小到几乎感觉不到。量化这门手艺本质上是在精度、速度、显存之间找平衡点。它不需要你重新训练模型也不需要你买新卡只要你会校准、会评估、会挑敏感层就能把一个“跑不动”的模型救活。以后如果还要往下压空间新的思路也会层出不穷但核心还是这篇文章里说的那件事理解误差从哪里来再去决定把它放到哪里去。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑