第1章:模型压缩与推理加速#

让大模型"瘦身",从显存杀手变成生产力工具。


目录#


第一节:量化技术详解#

1.1 量化技术概览#

量化 (Quantization) 是将模型权重和激活值从高精度(如 FP16/BF16)转换为低精度(如 INT8, INT4)的过程。

核心收益

  1. 显存占用剧减:INT4 模型显存仅为 FP16 的 1/4。
  2. 内存带宽压力减轻:这是 LLM 推理的主要瓶颈。
  3. 计算加速:整数运算比浮点运算更快(取决于硬件支持)。

主流方案对比 (SOTA)

特性GPTQAWQEXL2 (ExLlamaV2)bitsandbytes (BnB)
全称GPT-QuantizationActivation-aware Weight QuantizationExLlamaV2 Quantization-
核心原理逐层量化,利用Hessian矩阵最小化误差保护1%的关键"显著"权重通道混合精度量化 (2-8 bit混合)运行时动态量化 (LLM.int8())
量化时间慢 (需校准数据)较快 (需校准数据)慢 (极其精细的搜索)无 (加载时量化)
推理速度极快 (针对性CUDA优化)较慢 (非计算密集型)
主要用途早期主流,通用性好边缘端、低比特高精度生产环境高性能推理训练微调 (QLoRA)
显存颗粒度固定 (4-bit/8-bit)固定灵活 (如 4.65 bpw)固定

1.2 GPTQ vs AWQ vs EXL2 深度解析#

1. GPTQ (Generative Pre-trained Transformer Quantization)#

早期最流行的 Post-Training Quantization (PTQ) 方法。

  • 原理:基于 OBS (Optimal Brain Surgeon) 理论,通过二阶信息(Hessian 逆矩阵)来补偿量化带来的误差。它不是简单地四舍五入,而是调整未量化的权重来弥补已量化权重造成的损失。
  • 关键点:逐列更新权重,误差最小化。

2. AWQ (Activation-aware Weight Quantization)#

  • 核心发现:权重的重要性并不是平等的。大约 1% 的权重通道对精度影响巨大,而这些通道通常对应较大的激活值(Activation)。
  • 原理:不直接保护权重,而是保护对应激活值较大的权重通道。通过缩放(Scaling)技巧,将量化误差从重要权重转移到非重要权重上。
  • 优势:这种“激活感知”比 GPTQ 的盲目数学优化在某些场景下有更好的泛化能力,且主要为了这种格式设计了极快的推理 Kernel。

3. EXL2 (ExLlamaV2)#

这是目前单卡推理速度最快的量化格式。

  • 原理:不仅仅是 4-bit。EXL2 允许混合精度,例如可以设定目标为 4.65 bpw (bits per weight)。它会根据每一层对整体误差的敏感度,给重要的层分配 5-bit 或 6-bit,给不重要的层分配 3-bit 或 2-bit。
  • 优势
    • 显存利用率极致:可以正好卡在 24GB 显存显卡中塞入 70B 模型的极度压缩版,或者 34B 模型的高精度版。
    • 推理速度:作者重写了全套 CUDA Kernel,速度极快。

1.3 实战:使用 AutoGPTQ 和 AutoAWQ#

准备环境#

pip install auto-gptq autoawq optimum

脚本 1: 使用 AutoGPTQ 量化 LLaMA-3-8B#

from transformers import AutoTokenizer
from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig

# 1. 设定路径
model_id = "meta-llama/Meta-Llama-3-8B"
quantized_model_dir = "Llama-3-8B-GPTQ-4bit"

# 2. 准备分词器
tokenizer = AutoTokenizer.from_pretrained(model_id, use_fast=True)

# 3. 准备量化数据 (校准集)
# GPTQ 需要看少量真实数据来计算 Hessian 矩阵
examples = [
    tokenizer("Automated quantization is amazing!", return_tensors="pt"),
    tokenizer("Large language models are the future.", return_tensors="pt"),
    # ... 在生产环境中,这里应该加载真实数据集的子集,如 wikiText2 或 C4
]

# 4. 配置量化参数
quantize_config = BaseQuantizeConfig(
    bits=4,             # 量化到 4-bit
    group_size=128,     # 典型的 group size,越小精度越高但显存略增
    desc_act=False,     # 是否根据激活值重排 (提高精度但可能影响推理速度)
)

# 5. 加载模型并量化
model = AutoGPTQForCausalLM.from_pretrained(
    model_id,
    quantize_config=quantize_config,
    device_map="auto"
)

# 开始量化
print("开始量化...")
model.quantize(examples)

# 6. 保存
model.save_quantized(quantized_model_dir)
tokenizer.save_pretrained(quantized_model_dir)
print(f"量化完成,已保存至 {quantized_model_dir}")

脚本 2: 使用 AutoAWQ 量化#

from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

model_path = "meta-llama/Meta-Llama-3-8B"
quant_path = "Llama-3-8B-AWQ-4bit"
quant_config = {
    "zero_point": True,
    "q_group_size": 128,
    "w_bit": 4,
    "version": "GEMM"
}

# 1. 加载模型
model = AutoAWQForCausalLM.from_pretrained(model_path)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)

# 2. 量化
# AWQ 也需要校准集来寻找"显著"通道
print("开始 AWQ 量化...")
model.quantize(
    tokenizer,
    quant_config=quant_config,
    calib_data="pileval" # AutoAWQ 内置支持一些数据集名称,也可以传 list
)

# 3. 保存
model.save_quantized(quant_path)
tokenizer.save_pretrained(quant_path)
print(f"AWQ 量化完成: {quant_path}")

第二节:KV Cache 量化 (前沿趋势)#

2.1 什么是 KV Cache?为什么它是显存杀手?#

在 LLM 生成过程中,每生成一个 Token,都需要之前所有 Token 的 Key 和 Value 矩阵参与计算。为了加速,我们把这些矩阵存在显存里,这就是 KV Cache

  • 问题:随着上下文长度(Context Length)增加,KV Cache 呈线性增长。
  • 计算公式: $$ \text{Size} = 2 \times \text{Batch} \times \text{Layers} \times \text{Heads} \times \text{Head_Dim} \times \text{Seq_Len} \times \text{Precision} $$
  • 示例:对于 LLaMA-3-70B,FP16 精度,Batch=1,Sequence=128k:
    • 显存占用可能高达 数十GB,甚至超过模型权重本身!

2.2 K-V Cache Quantization (FP8 / INT4)#

为了解决长窗口(Long Context)推理的显存瓶颈,仅量化权重已经不够了,必须对 KV Cache 动刀。

趋势:从 FP16 KV Cache -> FP8 KV Cache (甚至 INT4)。

原理

  • Key 和 Value 矩阵的数值分布通常比权重更不规则(存在 Outliers)。
  • 但是,通过合适的 scale factor,可以将它们压缩到 FP8 (e4m3 或 e5m2 格式)。
  • vLLMFlashAttention 已经原生支持 FP8 KV Cache。

收益

  • 显存减半:128k 上下文的显存需求直接减半。
  • 吞吐增加:同等显存下,可以支持 Batch Size 翻倍。

vLLM 中开启 KV Cache 量化

只是启动时的简单参数:

# 启动 vLLM server 时添加 --kv-cache-dtype
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Meta-Llama-3-8B-Instruct \
    --kv-cache-dtype fp8

vLLM 会自动处理 FP8 的转换。对于一些新模型,这几乎是无损的。


第三节:剪枝与蒸馏 (简介)#

虽然量化是当前最主流的手段,但剪枝和蒸馏在端侧模型(On-Device LLM)中仍占有一席之地。

3.1 结构化剪枝 (Structured Pruning)#

  • 原理:直接移除模型中的整行、整列、甚至整层。
  • LLM-Pruner:通过分析梯度信息,通过移除对 Loss 影响最小的结构。
  • 稀疏度:通常 LLM 很难在剪枝超过 20%-30% 的情况下保持核心推理能力,这也是为什么目前量化(可以压到 25% 体积)比剪枝更受欢迎的原因。

3.2 知识蒸馏 (Knowledge Distillation)#

  • 原理:Teacher 模型(如 GPT-4)指导 Student 模型(如 LLaMA-1B)。
  • 白盒蒸馏:Student 学习 Teacher 的 Logits 分布(不仅学答案,还学"为什么")。
  • 黑盒蒸馏:Student 仅学习 Teacher 生成的文本数据(合成数据训练)。目前 DeepSeek-R1-Distill 系列就是这种模式,效果惊人。

第1章小结#

  1. 首选量化:对于生产环境,AWQGPTQ 是标准选择。如果有极致性能需求且有时间调试,EXL2 是最佳选择。
  2. KV Cache 也要压:长文本时代,FP8 KV Cache 是标配,能极大提升吞吐和最大上下文长度。
  3. 工具链成熟AutoGPTQAutoAWQ 让量化变得像 model.save() 一样简单。

下一章预告: 模型压缩只是第一步。如何把压缩后的模型变成为数千人服务的高性能 API?我们将深入 vLLM 及其核心技术 PagedAttention

[统计组件仅在生产环境显示]