GPTQ / AWQ / W4A16:大语言模型权重量化实战

使用 70 GB 显存才能跑一次的 Llama-2-70B,量化后可以塞进 24 GB 的消费级显卡。这不是魔法,而是大语言模型(LLM)权重量化带来的实际收益。本文将深入讲解 GPTQ、AWQ、SmoothQuant、W4A16 等主流量化方案的原理与实战,帮助你在生产环境中实现 4 倍模型压缩而

使用 70 GB 显存才能跑一次的 Llama-2-70B,量化后可以塞进 24 GB 的消费级显卡。这不是魔法,而是大语言模型(LLM)权重量化带来的实际收益。本文将深入讲解 GPTQ、AWQ、SmoothQuant、W4A16 等主流量化方案的原理与实战,帮助你在生产环境中实现 4 倍模型压缩而不显著牺牲精度。


一、为什么 LLM 量化与普通 CNN 不同

传统图像模型的后训练量化(PTQ)在 ResNet 上效果很好,但直接套用到 LLM 上时,困惑度(Perplexity)会急剧上升,生成结果质量显著下降。根本原因在于 LLM 激活分布中存在的幂律异常值(power-law outliers)

在 Transformer 的各层中,激活张量的大部分元素集中在很小的区间内,但少量通道(通常是特定的几个 token 维度)会爆发出极大值。这些离群值(outliers)占据了动态范围的主体,如果采用传统的 per-tensor 对称量化,大量正常值就会被压缩到极少数的量化格子中,导致信息严重丢失。

有趣的是,权重比激活更容易量化。权重分布通常接近高斯,没有极端离群点;而激活中与输入内容强相关的通道则难以预测。因此,LLM 量化领域的核心思路是:

  • 权重激进地压到 4-bit(4x 压缩)
  • 激活保留 8-bit 或 16-bit,或想办法把量化难度从激活迁移到权重

压缩目标非常明确:把动辄 70 GB、130 GB 的 FP16 权重降到 20 GB、35 GB 以下,让单卡甚至笔记本都能完成推理。


二、GPTQ:一次性层内贪心量化

2.1 理论根基:Optimal Brain Quantization

GPTQ 的数学基础是 OBQ(Optimal Brain Quantization),其思想来源于"最优脑损伤"(Optimal Brain Damage):每次量化一个权重时,不仅要考虑该权重自身的舍入误差,还要衡量它对其它未量化权重的"影响",并补偿性地更新剩余权重。

形式化地说,对于一个层的权重矩阵 $W$,目标是最小化量化后的输出重建误差:

$$
\min_{\hat{W}} |WX - \hat{W}X|^2
$$

其中 $X$ 是该层的校准数据(calibration data,通常只需 128~256 条样本)。OBQ 通过二阶信息(Hessian 矩阵 $H = X X^T$)来决定先量化哪个权重,以及如何更新剩余权重。

2.2 GPTQ 的核心加速技巧

OBQ 的原始复杂度是 $O(d_{row} \cdot d_{col}^3)$,对于 LLM 中动辄 4096 x 4096 甚至更大的矩阵根本无法接受。GPTQ 做了三个关键近似:

  1. 逐行独立量化:把权重矩阵按输出行拆开,每行独立求解,将问题降为 $O(d_{col}^2)$。
  2. 固定量化顺序:不再动态挑选"最好"的权重先量化,而是按固定顺序(例如从左到右)依次处理。实验表明这对最终精度影响很小。
  3. Cholesky 预计算:对 Hessian 矩阵做 Cholesky 分解,避免每一步都重复求逆。这是 GPTQ 相比 OBQ 提速数百倍的关键。

直观理解,GPTQ 就是:

拿一小批校准数据,逐层、逐行地把 FP16 权重舍入到最近的 4-bit 网格点;每量化完一个权重,就用闭式公式更新同一行中尚未量化的权重,以补偿已引入的误差。

2.3 AutoGPTQ 实战

from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig
from transformers import AutoTokenizer

model_id = "meta-llama/Llama-2-7b-hf"
tokenizer = AutoTokenizer.from_pretrained(model_id, use_fast=True)

# 准备校准数据(128~256 条即可)
examples = [
    tokenizer("auto-gptq is an easy-to-use model quantization library.")
    for _ in range(128)
]

quantize_config = BaseQuantizeConfig(
    bits=4,               # 4-bit 权重
    group_size=128,       # 分组量化,128 个权重共享一组缩放参数
    desc_act=False,       # 是否对激活降序排列(通常 False 更快)
)

model = AutoGPTQForCausalLM.from_pretrained(
    model_id, quantize_config, torch_dtype="auto"
)

# 执行一次性量化
model.quantize(examples, batch_size=1)

# 保存
model.save_quantized("./llama-2-7b-gptq-4bit")
tokenizer.save_pretrained("./llama-2-7b-gptq-4bit")

group_size=128 的意思是每 128 个连续权重共用一对缩放因子(scale / zero-point),这也叫分组量化block-wise quantization。group_size 越小,精度越高,但额外存储的开销也越大。


三、AWQ:激活感知的保护性量化

3.1 核心洞察:并非所有权重生而平等

AWQ(Activation-aware Weight Quantization)的作者观察到:虽然异常值出现在激活中,但造成这些异常值的"元凶"是与之相乘的少量权重通道。如果你把某些权重通道的重要性排序,会发现少数通道对最终输出质量具有不成比例的影响。

AWQ 的策略很巧妙:不是改变量化网格本身,而是对重要的权重通道施加一个微小的缩放因子,让量化后的舍入误差更多地落在不那么重要的通道上,从而保护"关键权重"。

3.2 与 QAT 的区别

值得注意的是,AWQ 不需要训练数据做反向传播。它通过分析激活幅值离线计算 per-channel scaling,整个过程是无梯度的后训练量化。这意味着:

  • 不需要大量训练数据
  • 不需要 GPU 做反向传播
  • 量化速度快,通常几分钟内完成

3.3 AutoAWQ 实战

from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

model_id = "meta-llama/Llama-2-7b-hf"
quant_config = {"zero_point": True, "q_group_size": 128, "w_bit": 4, "version": "GEMM"}

model = AutoAWQForCausalLM.from_pretrained(model_id, **quant_config)
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)

# 准备校准数据
data = []
for _ in range(128):
    data.append(tokenizer("AWQ quantization protects salient weight channels.")["input_ids"])

# 量化
model.quantize(tokenizer, quant_config=quant_config, calib_data=data)

model.save_quantized("./llama-2-7b-awq-4bit")
tokenizer.save_pretrained("./llama-2-7b-awq-4bit")

在大量公开评测中,AWQ 在相同 4-bit 压缩率下通常比 GPTQ 的困惑度低 5%~15%,尤其在代码生成和数学推理等对精度敏感的任务上优势更明显。


四、SmoothQuant:把量化难度从激活迁移到权重

GPTQ 和 AWQ 都聚焦于"权重量化",但激活依然保持 FP16 或 BF16。SmoothQuant 则提出了一个数学洞察:可以在不损失信息的前提下,把激活的量化难度"平滑"地迁移到权重上。

4.1 数学原理

对于一个线性层 $Y = XW$,引入一个按通道的缩放向量 $s > 0$:

$$
Y = (X \cdot \text{diag}(s)^{-1}) \cdot (\text{diag}(s) \cdot W) = \tilde{X} \cdot \tilde{W}
$$

其中:

  • $\tilde{X} = X \cdot \text{diag}(s)^{-1}$:把激活中难以量化的离群通道"压平",使其更适合 INT8 量化
  • $\tilde{W} = \text{diag}(s) \cdot W$:权重大不了变得稍微难量化一点,反正权重本来就比激活好量化

$s$ 的选择原则是:让迁移后的激活和权重都比较好量化。经验上,$s$ 通常取激活通道均值的某个幂次:

$$
s_j = \max(|X_j|)^\alpha / \max(|W_j|)^{1-\alpha}
$$

其中超参数 $\alpha$ 通常取 0.5,对激活较强的模型可以偏向 0.75。

4.2 实现效果

SmoothQuant 使 LLM 能够稳定地跑在 W8A8(8-bit 权重 + 8-bit 激活)配置上,相比原始 FP16:

  • 模型体积减半
  • 推理速度在 A100 上提升约 1.5~1.8x
  • 精度损失极小(通常不到 1% 的困惑度上升)

它已经集成到 FasterTransformer 和 TensorRT-LLM 中,是 NVIDIA GPU 上高吞吐推理的推荐方案之一。


五、W4A16 与其它主流格式

5.1 W4A16 的含义

W4A16 表示:权重Weight 以 4-bit 存储,激活Activation 和 KV-Cache 以 16-bit(FP16/BF16)计算。这是目前消费级 GPU 上最常见的部署形态:

  • 权重被压缩 4 倍,节省显存和 PCIe 带宽
  • 计算仍使用原生 FP16/BF16,不需要自定义 CUDA kernel 做 INT4 乘加(硬件不支持 INT4 乘加)

5.2 常见量化格式对比

格式说明位宽典型框架特点
GPTQ层内贪心重建量化W4A16AutoGPTQ, text-generation-inference通用性强,支持大量模型
AWQ激活感知保护量化W4A16AutoAWQ, vLLM同压缩率下精度更高
GGUF/GGMLllama.cpp 原生格式Q4_0, Q5_K_M, Q8_0llama.cpp, ollama, KoboldCppCPU 推理首选,跨平台
EXL2ExLlama2 专有格式混合 2~8 bitExLlama2支持自适应混合位宽,显存利用率高
NF4Normal Float 4W4A16 (QLoRA)bitsandbytes, PEFT用于微调而非部署,分布最优的 4-bit 类型
SmoothQuant平滑迁移量化难度W8A8FasterTransformer, TensorRT-LLM吞吐最高,需显卡支持 INT8 GEMM

5.3 NF4 与 GGUF 补充

NF4(Normal Float 4)是 QLoRA 提出的 4-bit 数据类型。与均匀分布的 INT4 不同,NF4 的量化格子按照标准正态分布的累积分布函数(CDF)逆映射来分配,使得对符合高斯分布的权重来说信息熵损失最小。NF4 主要用于微调场景(QLoRA),而非推理部署。

GGUF 是 llama.cpp 的新一代模型格式(代替旧的 GGML)。它将 tokenizer、超参数、权重全部打包进一个二进制文件。量化变体极其丰富:

  • Q4_0:最简单的 4-bit,速度快但精度一般
  • Q5_K_M:5-bit 混合精度,平衡速度和质量
  • Q8_0:8-bit,几乎无损,适合对质量要求极高的场景

六、bitsandbytes:LLM.int8() 与 8-bit Adam

6.1 LLM.int8() 混合精度分解

bitsandbytes 的 LLM.int8() 是 LLM 量化的先驱工作之一。它发现了一个关键现象:异常值只集中在极少数的隐藏维度上(通常不到 1% 的通道)。于是 LLM.int8() 采用混合精度分解

  • 对不含异常值的矩阵块,使用标准的 INT8 GEMM
  • 对包含异常值的列/行,退回到 FP16 进行计算
from transformers import AutoModelForCausalLM, BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_8bit=True,
    llm_int8_threshold=6.0,  # 超过此阈值的值视为异常值
)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=bnb_config,
    device_map="auto",
)

这种方法在 8-bit 下几乎能做到零精度损失,但相比 4-bit 量化,显存节省只有 2 倍而非 4 倍。

6.2 何时用 8-bit,何时用 4-bit?

场景推荐方案
显存极度紧张(如单卡 24GB 跑 70B 模型)GPTQ / AWQ 4-bit
追求最高生成质量,显存充裕LLM.int8() 或 Q8_0
需要继续微调(LoRA/QLoRA)bitsandbytes NF4 + LoRA
追求极致吞吐,部署在 A100/H100 集群SmoothQuant W8A8
在 macOS / CPU 上本地运行GGUF Q5_K_M / Q4_0

七、工程实战:从量化到部署

7.1 用 vLLM 部署 GPTQ/AWQ 模型

vLLM 的 PagedAttention 与量化权重配合,可以在单卡上获得惊人的吞吐:

from vllm import LLM, SamplingParams

# GPTQ 模型
llm = LLM(
    model="TheBloke/Llama-2-7B-GPTQ",
    quantization="gptq",      # 或 "awq"
    dtype="float16",
    gpu_memory_utilization=0.9,
)

sampling_params = SamplingParams(temperature=0.7, max_tokens=256)
outputs = llm.generate(["量化后的模型推理速度显著提升。"], sampling_params)

7.2 transformers 直接加载

from transformers import AutoModelForCausalLM, AutoTokenizer

# GPTQ
model = AutoModelForCausalLM.from_pretrained(
    "./llama-2-7b-gptq-4bit",
    device_map="auto",
)

# AWQ
model = AutoModelForCausalLM.from_pretrained(
    "./llama-2-7b-awq-4bit",
    device_map="auto",
)

对于 GPTQ 模型,如果本地加载时遇到 auto-gptq 相关错误,通常需要先 pip install auto-gptq;AWQ 同理需要 pip install autoawq

7.3 显存对比(Llama-2-70B)

配置权重显存KV-Cache(batch=1, 4K context)总显存占用适配显卡
FP16140 GB~20 GB~160 GB2x A100 80GB
GPTQ / AWQ W4A16~40 GB~20 GB~60 GB1x A100 80GB
GGUF Q4_K_M~40 GB~20 GB~60 GBCPU / 单卡
SmoothQuant W8A8~70 GB~10 GB~80 GB1x A100 80GB

可以看到,4-bit 量化让 70B 模型从专业级 8 卡集群降低到了单卡可运行的范围。


八、精度、速度、显存的全局权衡

以下汇总了本文涉及的所有主流方案,方便快速选型:

方法位宽VRAM 节省推理速度精度损失推荐框架
FP16/BF16 基线W16A161x1.0x0PyTorch, vLLM
LLM.int8()W8A16~2x0.9x极低transformers, bitsandbytes
SmoothQuantW8A8~2x1.5~1.8xTensorRT-LLM, FT
GPTQW4A16~4x0.8~1.0x中低AutoGPTQ, TGI, vLLM
AWQW4A16~4x0.8~1.0xAutoAWQ, vLLM
EXL2W2~8A162~8x(自适应)0.8~1.0x可调ExLlama2
QLoRA (NF4)W4A16~4x0.8x中(微调用)bitsandbytes + PEFT
GGUF Q4_0W4A16~4xCPU 可用中等llama.cpp
GGUF Q5_K_MW5A16~3.2xCPU 可用llama.cpp

选型建议

  • 个人开发 / 消费级显卡(RTX 4090 24GB):优先 AWQ 或 GPTQ W4A16,配合 vLLM 获得高吞吐
  • 苹果 MacBook / CPU 本地运行:用 llama.cpp 的 GGUF Q5_K_M,兼顾质量与速度
  • 数据中心批量推理(A100/H100):SmoothQuant W8A8 + TensorRT-LLM,吞吐最高
  • 低资源微调:QLoRA(NF4 + LoRA),在 16 GB 显存上微调 65B 模型
  • 极致压缩:EXL2 可以在不重要的层压到 23 bit,重要层保留 45 bit

结语

大模型量化已经从学术研究变成了推理部署的标配技术。GPTQ 和 AWQ 的普及,让 70B 参数模型也能在单张消费级显卡上流畅运行;SmoothQuant 则为数据中心的高吞吐场景提供了 W8A8 方案;llama.cpp 的 GGUF 生态让 LLM 真正走到了边缘设备和普通笔记本上。

在实际选型时,不必追求"最先进",而应根据硬件限制、精度要求、吞吐目标三者综合权衡。4-bit 权重量化已经相当成熟,AWQ 在多数场景下是新项目的推荐起点;如果只是想在本地笔记本跑一跑开源模型,直接下载社区已经量化好的 GGUF 文件即可。量化技术的持续进步,正在将"大模型"变得越来越"小",也越来越触手可及。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「ai」更多文章

  1. 模型量化技术详解:INT8、FP16 与混合精度推理
  2. 模型剪枝与知识蒸馏:从压缩到加速全链路
  3. 推理引擎终极对比:TensorRT vs ONNX Runtime vs OpenVINO