Skip to content

模型量化选型实战:GGUF / AWQ / GPTQ 到底怎么选 ​

部署大模型时最常见的三个问题:

  1. 显存装不下——64G 的模型想塞进 24G 显卡,除了量化还能怎么办?
  2. 量化完反而更慢——明明权重小了 4 倍,吞吐却没涨,甚至倒退。
  3. 精度悄悄掉了——通用评测看着还行,上线后业务效果就是不对。

这三个问题的根子都是同一件事:没搞清楚量化在动什么、没动什么。 这篇先把账算清楚,再谈选型。


1. 先算账:显存到底花在哪 ​

选量化方案之前,必须能估算「我要多少显存」。拍脑袋买卡是最贵的错误。

推理时的显存由三块构成,量化通常只解决第一块:

注意最后一行:绝大多数人说的「我做了量化」,指的只是把权重压到 4bit。激活值和 KV Cache 往往原封不动。这就是「权重小了 4 倍,显存却没降那么多」的直接原因。

1.1 权重要多少显存 ​

权重显存 ≈ 参数量 × 每个参数的字节数
精度每参数字节32B 模型70B 模型
FP16 / BF16264 GB140 GB
INT8132 GB70 GB
INT40.516 GB35 GB

1.2 KV Cache 要多少显存 ​

这一块最容易被忽略,也最容易在长上下文下突然爆掉:

KV Cache = 2 × 层数 × KV 头数 × head_dim × 字节数 × 序列长度 × 并发数
         └ K 和 V 两份

以 Qwen2.5-32B 这类配置为例(64 层、8 个 KV 头、head_dim 128,FP16):

上下文单并发 KV Cache权重(INT4) + KV24G 显卡
8K≈ 2 GB≈ 18 GB✅ 能跑
32K≈ 8 GB≈ 24 GB⚠️ 顶满,无余量
128K≈ 32 GB≈ 48 GB❌ 装不下

注意 KV Cache 随上下文线性增长,而它默认是 FP16 的。把上下文从 8K 开到 32K,KV Cache 直接翻 4 倍——这一步吃掉的空间,可能比你量化权重省下来的还多。

下面这张图把上面的账画在一起,那条红色虚线就是 24G 显卡的天花板:

同一个 32B 模型在 FP16、INT8、INT4 精度下的显存占用对比

核心结论

量化权重只解决「装得下」,不解决「跑得动」。 如果你的瓶颈在长上下文或高并发,光压权重没用,必须同时处理 KV Cache(开 KV 量化、限制上下文、或用分页注意力)。


2. 四种主流量化格式 ​

市面上能直接下载到的量化模型,基本就这四类。它们服务于不同的推理场景,不是互相替代关系:

格式量化对象典型工具精度适合场景
GGUF权重(CPU/GPU 混合)llama.cpp / Ollama / LM StudioQ4_K_M 起可用单机、Mac、CPU 推理、离线部署
AWQ权重(仅权重,4bit)vLLM / TensorRT-LLM / SGLang4bit 下较好GPU 高吞吐在线服务
GPTQ权重(仅权重,3~4bit)vLLM / Transformers / TGI4bit 下较好生态兼容性要求高
bitsandbytes NF4权重(4bit)Transformers / PEFT可接受微调(QLoRA),不是推理首选

2.1 GGUF:为「能跑起来」而生 ​

GGUF 是 llama.cpp 的格式,特点是分层卸载——可以把一部分层放 GPU、一部分放 CPU/内存,甚至纯 CPU 跑。

它有一整套 k-quant 命名,理解后缀比记名字重要:

后缀含义建议
Q8_08bit几乎无损,体积大
Q6_K6bit接近无损,性价比高的上限
Q4_K_M4bit,中等粒度默认首选,体积/质量平衡最好
Q3_K_M3bit开始明显掉点
Q2_K2bit只适合「跑通即可」的验证

⚠️ GGUF 不能喂给 vLLM。这是最常被问的兼容性问题——vLLM 不读 GGUF,要用 AWQ 或 GPTQ 版本。

2.2 AWQ:GPU 服务的默认答案 ​

AWQ 的核心洞察是:权重并非同等重要,一小部分「显著权重」决定了大部分精度。它的做法是用激活值的分布去识别这些显著通道,对它们做保护性缩放,从而在 4bit 下保住精度[1]。

在 vLLM 里基本是开箱即用:

bash
vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.9

2.3 GPTQ:生态最广的选择 ​

GPTQ 用近似二阶信息做一次性权重量化,能把 175B 模型压到 3~4bit 而精度损失可忽略,是这条路线上的奠基工作[2]。

它的优势不是精度最好,而是几乎所有框架都支持:vLLM、TGI、Transformers、ExLlama,模型仓库里的 -GPTQ-Int4 版本也最齐全。遇到"AWQ 版本找不到"时,GPTQ 通常有。


3. 选型决策 ​

把前面的分析收敛成一张图:

一句话版本:

  • 单机 / Mac / 无 GPU → GGUF
  • GPU 在线服务 → AWQ(有就用),GPTQ(兼容兜底)
  • 要微调 → bitsandbytes NF4
  • 显存够 → 别量化

4. 量化粒度:为什么默认是 group_size=128 ​

同样叫「4bit」,精度可能差很多,差别在粒度。

INT4 的最小单位是 0(能表示的值很少),如果整层共用一个缩放系数,权重分布稍有偏差就会集体跑偏。按 128 个权重一组分配 scale 和 zero-point,是精度和开销的常见折中。

代价也很具体:每组要额外存 2 个 FP16 参数(scale + zero),平均下来

每权重额外开销 = 2 × 16 bit ÷ 128 ≈ 0.25 bit

所以 INT4 + group_size=128 的真实体积大约是 4.25 bit/权重,而不是 4.0。估算显存时别按理论值算,会差出几个 GB。


5. 实操:三种主流加载方式 ​

bash
# ① GGUF —— 用 Ollama(最省事)
ollama run qwen2.5:7b-instruct-q4_K_M

# ② GGUF —— llama.cpp 直接跑
./llama-cli -m qwen2.5-7b-instruct-q4_k_m.gguf -p "你好" -n 128

# ③ AWQ / GPTQ —— vLLM 起服务
vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ --max-model-len 8192

Transformers 里加载 4bit(推理可用,但吞吐不如 vLLM):

python
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

bnb = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",          # NF4 比 fp4 更适合正态分布的权重
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,     # 二次量化,再省一点
)

model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen2.5-7B-Instruct",
    quantization_config=bnb,
    device_map="auto",
)

6. 量化后精度掉了,怎么定位 ​

这是最折磨人的问题,因为通用 benchmark 往往看不出来。

6.1 别看 perplexity,看你的任务 ​

困惑度(perplexity)对量化不敏感——掉 0.1 你可能觉得没事,但业务上的结构化输出可能已经开始崩了。必须用你自己的评测集,重点看这几类:

观察项为什么关键
指令遵循4bit 后最容易退化的能力
JSON / 结构化输出格式错误的概率明显上升
长链推理(数学、代码)中间步骤容易断
长上下文召回与 KV Cache 精度相关

6.2 逐层排查的实用手法 ​

不要一上来就换方案。按这个顺序试,成本从低到高:

  1. 换更保守的量化等级——GGUF 从 Q4_K_M 换 Q6_K,通常立竿见影
  2. 提高 group_size 精度——如果自己量化,把 group_size 从 128 降到 64
  3. 检查校准数据——AWQ/GPTQ 需要校准集,用通用语料校准一个垂直领域模型,是精度掉点的常见原因。换成业务语料重新量化
  4. 保留敏感层为 FP16——embedding、lm_head、第一层和最后一层对精度影响大,很多方案默认不量化它们

7. 踩坑清单 ​

现象原因解决
量化后显存没降多少只压了权重,KV Cache 和激活仍是 FP16开 KV 量化 / 限制 max_model_len / 降并发
4bit 反而比 FP16 慢该精度没有对应的高效 kernel,反量化开销吃掉了收益换 AWQ(有专门 kernel)或提升 batch 摊薄
把 GGUF 给 vLLM 报错vLLM 不读 GGUF换 AWQ / GPTQ 版本
按 4.0 bit 估算显存,实际超了group-wise 量化有额外元数据(约 +0.25 bit)按 4.25~4.5 bit 估算,留 10% 余量
长上下文一开就 OOMKV Cache 随序列线性增长,且默认 FP16见上一条;或改用支持分页注意力的框架
通用评测正常,业务效果差校准数据与业务分布不匹配用业务语料重新量化
自己量化出的模型比官方量化版差校准集、实现细节、是否保留敏感层都有差异优先用官方量化版,除非有明确理由
Mac 上跑 AWQ 失败AWQ/GPTQ 依赖 CUDA kernelMac 上用 GGUF(Metal 加速)

8. 小结 ​

要点说明
先算账再选型权重 = 参数量 × 字节数;KV Cache = 2 × 层 × KV头 × head_dim × 字节 × 序列 × 并发
量化权重 ≠ 省显存只解决静态部分;长上下文和高并发的瓶颈在 KV Cache
格式按场景选单机/CPU → GGUF;GPU 服务 → AWQ 优先、GPTQ 兜底;微调 → NF4
粒度决定精度group_size=128 是常见折中,实际体积约 4.25 bit/权重
优先用官方量化版自己量化的坑(校准集、敏感层)比想象中多
评估要用自己的数据perplexity 看不出问题,指令遵循和结构化输出才是重灾区

延伸阅读 ​

  1. Frantar E, Ashkboos S, Hoefler T, 等. GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers[EB/OL]. (2022)[2026-09-21]. https://arxiv.org/abs/2210.17323v2.
  2. Lin J, Tang J, Tang H, 等. AWQ: Activation-aware Weight Quantization for On-Device LLM Compression and Acceleration[J]. GetMobile: Mobile Computing and Communications, 2023. DOI: 10.1145/3714983.3714987.

📎 相关文章:CUDA OOM 排查实录 —— 显存已经爆了怎么救。

📖本文阅读--次|📊全站访问--次|👥访客--人