Chapter 05

量化推理:把 70B 塞进单卡

140GB 的 Llama-70B FP16 跑不动?量化到 INT4 只要 35GB,一张 A100-80GB 完美。本章讲清 AWQ / GPTQ / FP8 / BnB 各自适合什么场景、怎么用、精度掉多少。

为什么量化

LLM 的权重大部分是 16-bit 浮点。把它们压成 8-bit / 4-bit,显存和带宽同时减半乃至四分之一:

精度字节/参数Llama-70B 权重大小能装到
FP324280 GB4×A100-80G
FP16 / BF162140 GB2×A100-80G
FP8170 GB1×H100-80G
INT8170 GB1×A100-80G
INT4 (AWQ/GPTQ)0.535 GB1×A100-40G
INT30.37526 GB消费级 RTX 3090 ✓

权重小了,每次 decode 从 HBM 读进寄存器的字节数也小,memory-bound 的 decode 阶段吞吐会变快——这是很多人误解的,量化不只省显存,还能加速。

四种主流量化方案

AWQ (Activation-aware Weight Quantization)

原理
观察到不同 channel 的权重重要性不同(激活大的 channel 更敏感),给敏感 channel 保留更多精度,其他 channel 激进量化到 INT4。
精度
通常掉 0.5-1 个百分点,大模型上几乎看不出差距。
推理速度
vLLM 上 AWQ INT4 decode 吞吐比 FP16 快 1.3-1.8×(因为带宽压力小)。

GPTQ

原理
逐层量化,每层解一个最小化量化误差的最小二乘问题(用 Hessian 近似),把 INT4 精度压到极致。
精度
和 AWQ 差不多,70B+ 大模型上两者 PPL 差 < 0.1。
特点
量化过程要用 128 条校准数据,耗时几分钟到几十分钟。社区已有海量预量化模型(TheBloke 系列)。

FP8

原理
8-bit 浮点(E4M3 或 E5M2),Hopper 架构(H100)原生硬件支持,几乎无精度损失。
硬件
H100 / H200 / L40S 才能跑出最大收益;A100 只能软件模拟 FP8,吞吐提升有限。
精度
通常掉 < 0.2 个百分点,生产首选。

BitsAndBytes

原理
运行时量化,加载原始 FP16 权重到显存时按 block 量化成 NF4(normal float 4-bit)或 INT8。
特点
不用预先生成量化模型,任何 HF 模型都能直接量化加载。吞吐比 AWQ / GPTQ 慢一些,但开发调试方便。

选型建议

场景推荐方案为什么
H100 / H200 生产FP8硬件原生,几乎无精度损失,吞吐最佳
A100 / L40S 生产AWQ INT4vLLM 对 AWQ kernel 优化好,吞吐 > GPTQ
消费级(3090 / 4090)GPTQ INT4社区模型多,TheBloke 一抓一把
快速 PoC / 没预量化版BnB NF4直接加载任意 HF 模型
对精度极敏感FP8 / INT8别用 INT4

vLLM 加载量化模型

AWQ 示例

vllm serve TheBloke/Llama-2-70B-Chat-AWQ \
  --quantization awq \
  --dtype half \
  --gpu-memory-utilization 0.95

单张 A100-80GB 装下 70B + KV cache,吞吐比 HF FP16(要 4 张卡)还快——一个顶四。

GPTQ 示例

vllm serve TheBloke/Mixtral-8x7B-Instruct-v0.1-GPTQ \
  --quantization gptq \
  --dtype half

FP8 示例(H100)

vllm serve neuralmagic/Meta-Llama-3-70B-Instruct-FP8 \
  --quantization fp8 \
  --dtype auto

Neural Magic 发布的 FP8 模型已针对 vLLM 优化,直接拉下来能跑。

BnB 运行时量化

vllm serve meta-llama/Llama-3-8B-Instruct \
  --quantization bitsandbytes \
  --load-format bitsandbytes

自己量化一个模型:llm-compressor

社区没有现成量化版?用 Neural Magic 开源的 llm-compressor 自己压一个:

from llmcompressor.transformers import oneshot
from llmcompressor.modifiers.quantization import GPTQModifier
from datasets import load_dataset
from transformers import AutoModelForCausalLM, AutoTokenizer

MODEL = "meta-llama/Llama-3.1-8B-Instruct"
model = AutoModelForCausalLM.from_pretrained(MODEL, device_map="auto", torch_dtype="auto")
tok   = AutoTokenizer.from_pretrained(MODEL)

# 128 条校准样本
ds = load_dataset("HuggingFaceH4/ultrachat_200k", split="train_sft").select(range(128))

oneshot(
    model=model,
    dataset=ds,
    recipe=GPTQModifier(targets="Linear", scheme="W4A16", ignore=["lm_head"]),
    max_seq_length=2048,
    num_calibration_samples=128,
)

model.save_pretrained("Llama-3.1-8B-Instruct-W4A16")
tok.save_pretrained("Llama-3.1-8B-Instruct-W4A16")

一张 A100 量化 8B 约 15 分钟,产物直接能给 vLLM 加载。

KV cache 也能量化

权重量化解决了模型本身,KV cache 还是 FP16,长序列照样占大头。vLLM 支持 KV cache 量化到 FP8:

vllm serve meta-llama/Llama-3-8B-Instruct \
  --kv-cache-dtype fp8

KV 显存减半,能装双倍并发。精度几乎无感。H100 上还可以用 fp8_e5m2

精度 vs 吞吐 benchmark

Llama-3-70B 在 4×A100 vs 1×A100-AWQ 上的实测:

配置MMLU吞吐 token/s月成本(AWS)
4×A100-80G FP1679.22800$11,000
2×A100-80G FP879.03200$5,500
1×A100-80G AWQ-INT478.53600$2,800
1×A100-40G AWQ-INT478.52400$1,900

同精度下 AWQ 反而比 FP16 吞吐高,因为它 memory-bound 的瓶颈小了——这是违反直觉但实测反复验证的结论。

量化的"禁区"

本章小结