大模型量化:从原理到 4-bit 实战
大模型的能力随参数量增长而提升,但部署成本同样随参数量线性甚至超线性膨胀。一个 70B 参数的模型,仅权重以 FP16 存储就需要约 140 GB 显存,远超单张消费级显卡的容量。量化(Quantization)是缓解这一矛盾最成熟、最广泛使用的技术手段:它以可控的精度损失为代价,把模型权重与激活从高精度浮点(FP16/BF16/FP32)压缩到低比特整数(INT8/INT4 等),从而同时降低显存占用、提升推理吞吐。
本文系统梳理量化的动机、基础概念、四种代表性方法,以及用开源工具链以 4-bit 加载模型的实战代码。
一、为什么要量化:显存、带宽与延迟
要理解量化为什么有效,需要把「模型能不能装下」和「模型跑得快不快」拆开看。二者分别对应两个不同的瓶颈:显存容量瓶颈与内存带宽瓶颈。
1.1 显存容量:决定模型能否装下
模型权重是推理时最占显存的部分。以参数量 P 为例,不同精度下的纯权重体积约为:
FP32: 4 * P 字节
FP16 / BF16: 2 * P 字节
INT8: 1 * P 字节
INT4: 0.5 * P 字节
一个 7B 模型,FP16 下约 14 GB,INT8 约 7 GB,INT4 约 3.5 GB。量化到 INT4 后,许多原本需要多卡才能加载的模型可以被塞进单张 24 GB 的消费级显卡。需要注意的是,实际显存还包含优化器状态(训练时)、KV Cache、激活值与量化常数(scale/zero-point),因此真实占用会高于上述纯权重的下界。
1.2 内存带宽:决定推理是否够快
很多人误以为推理慢是因为「算力不够」。对自回归生成的 decode 阶段而言,每生成一个 token 都要把全部权重从显存读到计算单元,这个过程的耗时主要由「需要搬多少字节」决定,而非「能做多少次乘加」。在算力充足、带宽受限的内存墙(memory-bound)场景下,单 token 延迟可近似为:
单 token 延迟 ≈ (参数量 P * 每参数字节数) / 显存带宽
例如 A100 的 HBM 带宽约为 2 TB/s,70B 模型 FP16(140 GB)理论下限约 70 ms/token;量化到 INT8(70 GB)后约降为 35 ms/token。换言之,降低每参数比特数直接成比例地降低了带宽需求,这是量化能加速推理的根本原因。
1.3 三者的关系
显存容量决定「能不能跑」,内存带宽决定「跑多快」,而量化同时改善二者:低比特让模型更可能装下单卡,也让每次生成要搬运的数据更少。延迟的下降幅度,在内存受限场景下近似等于比特数下降的比例;在算力受限场景下,收益则取决于计算内核是否能真正利用低比特指令。这也是为什么实际加速比(如 1.5x 到 4x)会因硬件、内核实现与位宽而不同。
二、量化基础
2.1 INT8 与 INT4:位宽意味着什么
位宽直接决定可表示数值的粒度与压缩率。INT8 用 8 个比特表示 256 个整数级别,INT4 仅 16 个级别。位宽越低,压缩越好,但相邻可表示值之间的「台阶」越大,量化误差也越大。经验上 INT8 对多数任务几乎无损,INT4 是当前精度与体积之间最常用的甜点位,再往 3-bit、2-bit 推进则精度退化明显加快。
2.2 权重量化与激活量化
- 权重量化(weight-only quantization):只把模型权重压到低比特,计算时再反量化为高精度(或在专用低比特内核中计算)。它直接省下显存,实现简单,是 GPTQ、AWQ 等方法的路线。
- 激活量化(activation quantization):把每层前向传播的中间激活也压到低比特(如 W8A8)。这能进一步释放计算内核的吞吐,但激活中常存在极端离群值(outlier),量化难度远高于权重,这也是 SmoothQuant 等方法要解决的核心问题。
2.3 对称量化与非对称量化
量化本质是建立浮点值与整数值之间的仿射映射。最常见的是均匀量化。
对称量化假设数值关于零对称,只有一个缩放因子 scale:
量化: q = round(x / scale)
反量化: x' = q * scale
其中 scale = max(|x|) / (2^(b-1) - 1) # 以 INT8 为例,分母为 127
对称量化无零点(zero-point),计算轻量,适合分布大致关于零对称、无明显偏移的权重。
非对称量化额外引入零点 zero_point,把实数区间 [min, max] 映射到整数区间 [0, 2^b - 1]:
step = (max - min) / (2^b - 1)
zero_point = round(-min / step)
量化: q = round(x / step) + zero_point
反量化: x' = (q - zero_point) * step
非对称量化能更贴合有偏移的分布(例如 ReLU 后的激活恒非负),用少量额外存储(zero_point)换取更小的映射误差。
2.4 校准(Calibration)
scale 与 zero_point 不能凭空设定,而应根据「真实数据分布」确定。校准就是用一小批有代表性的样本(校准集,calibration set)统计激活或权重的分布,从而选出使量化误差最小的量化参数。常见策略包括:
- 最小最大值(min-max):直接用观测到的最大最小值,简单但易被个别离群值拉大 step;
- 百分位/裁剪(percentile clipping):用 99.9% 分位数代替最大值,抑制离群值影响;
- 熵(KL 散度)或均方误差(MSE)最小化:在原始分布与量化后分布之间选最优截断点。
校准集的质量直接影响低比特下的精度,因此多数 PTQ(训练后量化)方法都会强调校准数据的选取。
三、代表性量化方法
下面四种方法几乎覆盖了当前开源生态的主流路线,且都已有对应的工程实现。
3.1 LLM.int8():混合精度分解与离群特征
论文:Dettmers 等人,LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale(NeurIPS 2022,arXiv:2208.07339)。
作者发现, transformer 中存在一类「系统性涌现的离群特征」:少数特征维度的值域比其他维度高出约两个数量级。若对全部特征统一做 INT8,这些离群维度会产生巨大量化误差,进而拖累整体性能。
LLM.int8() 的解法是混合精度分解:
- 对绝大多数特征,采用 vector-wise 量化(矩阵乘法中每个内积单独计算归一化常数)压成 INT8;
- 对少数离群特征维度,单独拆出做 FP16 矩阵乘法,其余超过 99.9% 的数值仍在 8-bit 下完成。
结果是显存约减半,且对高达 175B 参数的模型几乎无性能退化。该方法由 bitsandbytes 库实现,是后续 4-bit 推理(如 QLoRA)的基础。
3.2 GPTQ:基于二阶信息的单步权重量化
论文:Frantar 等人,GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers(ICLR 2023,arXiv:2210.17323)。
GPTQ 是一种 one-shot(单步、无需训练)的权重量化方法,核心思想是用近似的二阶信息(基于 Hessian 的误差补偿)来最小化量化带来的层输出误差。它在逐层、逐列量化权重时,把当前列的量化误差按重要性补偿到尚未量化的列上,从而以很小的精度代价把位宽压到 3 或 4 bit。
论文报告:可在约 4 个 GPU 小时内量化 175B 模型到 3-4 bit,相对 FP16 基线精度损失极小;端到端推理相对 FP16 在 A100 上约加速 3.25 倍、在 A6000 上约加速 4.5 倍。GPTQ 是权重-only 4-bit 生态的奠基性工作,社区实现以 AutoGPTQ 为代表。
3.3 SmoothQuant:把激活的难度迁移到权重
论文:Xiao 等人,SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models(ICML 2023,arXiv:2211.10438)。
SmoothQuant 的目标是做到 W8A8——权重和激活都量化到 INT8,从而充分利用低比特计算内核。它的关键观察是:权重容易量化,而激活难量化(因为激活包含离群值)。既然「难量化」源于激活的离群幅度,那么可以通过一个数学上等价的变换,把量化难度从激活「迁移」到权重上:
对某一通道: Y = X * W
引入缩放向量 s(按通道):
X' = X * diag(s)
W' = W * diag(1/s)
则 X' * W' = X * W = Y # 等价变换,结果不变
通过适当选择 s(让激活与权重的量化难度均衡),激活的离群幅度被「摊平」,权重则承担更多可量化的幅度变化。SmoothQuant 据此实现全矩阵乘法的 INT8 量化,论文报告最高约 1.56 倍加速与 2 倍显存下降,且对 OPT、BLOOM、LLaMA 等系列模型均有效。
3.4 AWQ:激活感知的权重量化
论文:Lin 等人,AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration(MLSys 2024 最佳论文,arXiv:2306.00978)。
AWQ 同样走权重-only 低比特路线,但其洞察很独特:并不是所有权重都同等重要。论文发现,只要保护约 1% 的「显著权重通道」(salient weights),就能大幅降低量化误差。关键在于——哪些通道显著,应当看激活分布而不是权重本身的大小。
做法上,AWQ 通过离线统计激活,为显著通道计算一个缩放系数,并用等价变换把这些通道「放大」,使其相对量化台阶更鲁棒;其余通道正常量化。它不依赖反向传播或重建,因此不易过拟合校准集,对指令微调模型、多模态模型也能较好泛化。AWQ 配套了 TinyChat 推理框架,在桌面与移动端 GPU 上相对 FP16 实现可获得 3 倍以上加速。
四、量化对精度与困惑度的影响
量化终究是用精度换效率,trade-off 是绕不开的话题。实践中常用困惑度(Perplexity,PPL,越低越好,多见于 WikiText2 评测)来衡量语言建模能力的变化,并用下游任务准确率验证可用性。
几个有依据的经验性结论:
- INT8 权重量化通常几乎无损,困惑度与 FP16 非常接近;
- INT4 权重-only 量化(GPTQ、AWQ)在良好校准下,困惑度上升通常很小,仍可保持可用甚至接近基线的能力,是当前最流行的部署配置;
- 激进位宽(3-bit、2-bit 或更低)会带来明显的困惑度恶化与任务掉点,需要更精细的方法或阶段性量化才可控;
- 激活量化到 4-bit(W4A4)比权重-only 4-bit 难得多,因为激活离群值更难压住,这正是 LLM.int8() 与 SmoothQuant 重点攻关的方向。
取舍的原则是:先确定可接受的精度红线(例如困惑度上升不超过某阈值、下游任务不掉点超过某比例),再据此选择能压到的最低位宽与是否做激活量化。对绝大多数部署场景,「4-bit 权重-only + 高精度计算内核」是体积、速度与精度之间性价比最高的落点。
五、实战:以 4-bit 加载大模型
下面给出三种主流、可运行的加载方式。所有示例均只做推理加载与一次生成,便于验证量化模型是否「能正常说话」。
5.1 使用 transformers + bitsandbytes(NF4)
bitsandbytes 由 LLM.int8() 团队维护,transformers 原生支持通过其 BitsAndBytesConfig 以 4-bit 加载任意兼容模型,无需预先量化好的权重文件。
所需包:torch、transformers、bitsandbytes、accelerate。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
# 4-bit 量化配置:NF4 针对近似正态的权重分布,配合双重量化进一步省显存
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4", # 4-bit 正态浮点,比纯 INT4 更贴合权重分布
bnb_4bit_compute_dtype=torch.bfloat16, # 计算时反量化为 bf16
bnb_4bit_use_double_quant=True, # 对量化常数再做一次量化,再省约 0.4 bit/参数
)
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
quantization_config=bnb_config,
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
inputs = tokenizer("量化后的模型能正常推理吗?", return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=64)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
说明:bitsandbytes 的 8-bit/4-bit 推理依赖 NVIDIA CUDA 内核,主要在 CUDA GPU 上可用。
5.2 使用 auto-gptq 加载 GPTQ 模型
该方式需要模型权重本身已由 GPTQ 算法预先量化(Hugging Face Hub 上有大量 *-GPTQ 仓库)。transformers 可直接加载,底层由 auto-gptq 提供内核。
所需包:torch、transformers、auto-gptq。
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "TheBloke/Llama-2-7B-GPTQ"
model = AutoModelForCausalLM.from_pretrained(
model_id,
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained(model_id)
inputs = tokenizer("量化后的模型能正常推理吗?", return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=64)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
提示:原 AutoGPTQ 仓库已进入未维护状态,社区继任项目为 GPTQModel;新模型与问题修复建议迁移到 GPTQModel,但 API 形态相近。
5.3 使用 autoawq 加载 AWQ 模型
同理,需要模型已按 AWQ 算法量化(Hub 上常见 *-AWQ 仓库)。autoawq 提供专用加载入口。
所需包:torch、transformers、autoawq。
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
model_id = "TheBloke/Llama-2-7B-AWQ"
# from_quantized 直接加载 4-bit 权重,并融合层以提升推理效率
model = AutoAWQForCausalLM.from_quantized(model_id, fuse_layers=True)
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
inputs = tokenizer("量化后的模型能正常推理吗?", return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=64)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
三种方式如何选择:想对「任意 HF 模型」即时做 4-bit 而不准备量化权重,选 bitsandbytes;想用社区已发布的 GPTQ/AWQ 权重获得更高、更稳定的压缩与吞吐,分别选 auto-gptq / autoawq。无论哪种,都建议用一小段真实输入验证输出连贯性,再上线到生产。
小结
量化通过把权重与激活从高精度浮点压到低比特整数,同时缓解显存容量瓶颈与内存带宽瓶颈,是降低大模型部署成本最成熟的手段。基础层面要分清 INT8/INT4 的位宽取舍、权重量化与激活量化、对称/非对称量化以及校准的作用。方法层面,LLM.int8() 用混合精度分解处理离群特征,GPTQ 用二阶误差补偿做高质量的 one-shot 权重量化,SmoothQuant 通过等价变换把激活的量化难度迁移到权重以实现 W8A8,AWQ 则依据激活分布保护约 1% 显著权重通道来做 4-bit 权重-only 量化。精度上,INT8 近乎无损、INT4 是当前性价比甜点、更低位宽需谨慎。实战中可用 transformers + bitsandbytes 即时做 4-bit,或用 auto-gptq / autoawq 加载社区已量化权重,落地门槛已经很低。
参考与延伸阅读
- Dettmers, T., Lewis, M., Belkada, Y., Zettlemoyer, L. (2022). LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale. NeurIPS 2022. arXiv:2208.07339. https://arxiv.org/abs/2208.07339
- Frantar, E., Ashkboos, S., Hoefler, T., Alistarh, D. (2022). GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers. ICLR 2023. arXiv:2210.17323. https://arxiv.org/abs/2210.17323
- Xiao, G., Lin, J., Seznec, M., Wu, H., Demouth, J., Han, S. (2022). SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models. ICML 2023. arXiv:2211.10438. https://arxiv.org/abs/2211.10438
- Lin, J., Tang, J., Tang, H., Yang, S., Chen, W., Wang, W., Xiao, G., Dang, X., Gan, C., Han, S. (2023). AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration. MLSys 2024(最佳论文). arXiv:2306.00978. https://arxiv.org/abs/2306.00978
- bitsandbytes(LLM.int8() 与 4-bit 推理官方实现,Dettmers 等维护). https://github.com/bitsandbytes-foundation/bitsandbytes
- AutoGPTQ(基于 GPTQ 算法的官方量化包,现已未维护,建议迁移 GPTQModel). https://github.com/PanQiWei/AutoGPTQ
- AutoAWQ(实现 AWQ 算法的 4-bit 量化工具包). https://github.com/casper-hansen/AutoAWQ
- GPTQ 原作官方代码仓库(IST-DASLab/gptq). https://github.com/IST-DASLab/gptq
- SmoothQuant 原作官方代码仓库(mit-han-lab/smoothquant). https://github.com/mit-han-lab/smoothquant
- AWQ 原作官方代码仓库(mit-han-lab/llm-awq). https://github.com/mit-han-lab/llm-awq