模型量化选型实战:GGUF / AWQ / GPTQ 到底怎么选
部署大模型时最常见的三个问题:
- 显存装不下——64G 的模型想塞进 24G 显卡,除了量化还能怎么办?
- 量化完反而更慢——明明权重小了 4 倍,吞吐却没涨,甚至倒退。
- 精度悄悄掉了——通用评测看着还行,上线后业务效果就是不对。
这三个问题的根子都是同一件事:没搞清楚量化在动什么、没动什么。 这篇先把账算清楚,再谈选型。
1. 先算账:显存到底花在哪
选量化方案之前,必须能估算「我要多少显存」。拍脑袋买卡是最贵的错误。
推理时的显存由三块构成,量化通常只解决第一块:
注意最后一行:绝大多数人说的「我做了量化」,指的只是把权重压到 4bit。激活值和 KV Cache 往往原封不动。这就是「权重小了 4 倍,显存却没降那么多」的直接原因。
1.1 权重要多少显存
权重显存 ≈ 参数量 × 每个参数的字节数| 精度 | 每参数字节 | 32B 模型 | 70B 模型 |
|---|---|---|---|
| FP16 / BF16 | 2 | 64 GB | 140 GB |
| INT8 | 1 | 32 GB | 70 GB |
| INT4 | 0.5 | 16 GB | 35 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) + KV | 24G 显卡 |
|---|---|---|---|
| 8K | ≈ 2 GB | ≈ 18 GB | ✅ 能跑 |
| 32K | ≈ 8 GB | ≈ 24 GB | ⚠️ 顶满,无余量 |
| 128K | ≈ 32 GB | ≈ 48 GB | ❌ 装不下 |
注意 KV Cache 随上下文线性增长,而它默认是 FP16 的。把上下文从 8K 开到 32K,KV Cache 直接翻 4 倍——这一步吃掉的空间,可能比你量化权重省下来的还多。
下面这张图把上面的账画在一起,那条红色虚线就是 24G 显卡的天花板:
核心结论
量化权重只解决「装得下」,不解决「跑得动」。 如果你的瓶颈在长上下文或高并发,光压权重没用,必须同时处理 KV Cache(开 KV 量化、限制上下文、或用分页注意力)。
2. 四种主流量化格式
市面上能直接下载到的量化模型,基本就这四类。它们服务于不同的推理场景,不是互相替代关系:
| 格式 | 量化对象 | 典型工具 | 精度 | 适合场景 |
|---|---|---|---|---|
| GGUF | 权重(CPU/GPU 混合) | llama.cpp / Ollama / LM Studio | Q4_K_M 起可用 | 单机、Mac、CPU 推理、离线部署 |
| AWQ | 权重(仅权重,4bit) | vLLM / TensorRT-LLM / SGLang | 4bit 下较好 | GPU 高吞吐在线服务 |
| GPTQ | 权重(仅权重,3~4bit) | vLLM / Transformers / TGI | 4bit 下较好 | 生态兼容性要求高 |
| bitsandbytes NF4 | 权重(4bit) | Transformers / PEFT | 可接受 | 微调(QLoRA),不是推理首选 |
2.1 GGUF:为「能跑起来」而生
GGUF 是 llama.cpp 的格式,特点是分层卸载——可以把一部分层放 GPU、一部分放 CPU/内存,甚至纯 CPU 跑。
它有一整套 k-quant 命名,理解后缀比记名字重要:
| 后缀 | 含义 | 建议 |
|---|---|---|
Q8_0 | 8bit | 几乎无损,体积大 |
Q6_K | 6bit | 接近无损,性价比高的上限 |
Q4_K_M | 4bit,中等粒度 | 默认首选,体积/质量平衡最好 |
Q3_K_M | 3bit | 开始明显掉点 |
Q2_K | 2bit | 只适合「跑通即可」的验证 |
⚠️ GGUF 不能喂给 vLLM。这是最常被问的兼容性问题——vLLM 不读 GGUF,要用 AWQ 或 GPTQ 版本。
2.2 AWQ:GPU 服务的默认答案
AWQ 的核心洞察是:权重并非同等重要,一小部分「显著权重」决定了大部分精度。它的做法是用激活值的分布去识别这些显著通道,对它们做保护性缩放,从而在 4bit 下保住精度[1]。
在 vLLM 里基本是开箱即用:
vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ \
--max-model-len 8192 \
--gpu-memory-utilization 0.92.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. 实操:三种主流加载方式
# ① 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 8192Transformers 里加载 4bit(推理可用,但吞吐不如 vLLM):
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 逐层排查的实用手法
不要一上来就换方案。按这个顺序试,成本从低到高:
- 换更保守的量化等级——GGUF 从 Q4_K_M 换 Q6_K,通常立竿见影
- 提高 group_size 精度——如果自己量化,把 group_size 从 128 降到 64
- 检查校准数据——AWQ/GPTQ 需要校准集,用通用语料校准一个垂直领域模型,是精度掉点的常见原因。换成业务语料重新量化
- 保留敏感层为 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% 余量 |
| 长上下文一开就 OOM | KV Cache 随序列线性增长,且默认 FP16 | 见上一条;或改用支持分页注意力的框架 |
| 通用评测正常,业务效果差 | 校准数据与业务分布不匹配 | 用业务语料重新量化 |
| 自己量化出的模型比官方量化版差 | 校准集、实现细节、是否保留敏感层都有差异 | 优先用官方量化版,除非有明确理由 |
| Mac 上跑 AWQ 失败 | AWQ/GPTQ 依赖 CUDA kernel | Mac 上用 GGUF(Metal 加速) |
8. 小结
| 要点 | 说明 |
|---|---|
| 先算账再选型 | 权重 = 参数量 × 字节数;KV Cache = 2 × 层 × KV头 × head_dim × 字节 × 序列 × 并发 |
| 量化权重 ≠ 省显存 | 只解决静态部分;长上下文和高并发的瓶颈在 KV Cache |
| 格式按场景选 | 单机/CPU → GGUF;GPU 服务 → AWQ 优先、GPTQ 兜底;微调 → NF4 |
| 粒度决定精度 | group_size=128 是常见折中,实际体积约 4.25 bit/权重 |
| 优先用官方量化版 | 自己量化的坑(校准集、敏感层)比想象中多 |
| 评估要用自己的数据 | perplexity 看不出问题,指令遵循和结构化输出才是重灾区 |
延伸阅读
- 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.
- 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 排查实录 —— 显存已经爆了怎么救。