推理为什么比训练还贵

很多人以为大模型的成本主要在训练,其实上线后推理才是长期开销。训练是一次性投入,推理是每天每用户都在花钱。一个 7B 模型 FP16 加载就要 14GB 显存,每秒生成几十个 token,用户一多,显卡根本排不过来。

推理慢的原因有两个:一是模型权重本身占显存,二是自回归解码必须一个 token 一个 token 生成,没法并行。这两个问题分别对应两条优化路线:量化解决权重显存,KV Cache 和批处理解决解码效率。

推理优化的本质不是「让模型算得更快」,而是「让同一张卡同时服务更多用户、每次生成更省显存」。
本文核心知识点
  • 权重量化把 FP16 权重压到 INT8 甚至 INT4,显存减半甚至更多,精度损失很小。
  • KV Cache缓存历史注意力键值,避免每步重算,但随上下文线性增长。
  • PagedAttentionvLLM 的核心技术,把 KV Cache 分页管理,消除显存碎片。
  • 连续批处理动态拼接不同请求,让显卡始终跑满不空闲。
推理优化配图:中央发光芯片连接数据管线与上升指标,蓝色渐变扁平风格
推理优化的直观示意:芯片是核心,数据管线是吞吐,上升指标是优化效果。

权重量化:从 FP16 到 INT8

FP16 是半精度浮点数,每个权重占 16 位。量化就是把它压成 8 位整数(INT8)或者 4 位整数(INT4),显存直接减半甚至砍到四分之一。代价是数值精度降低,但实际测试发现,大模型对量化非常鲁棒——INT8 几乎不掉点,INT4 在大多数任务上也能用。

# 常见量化方式对比
# FP16:原始精度,显存最大
# INT8:对称量化,精度损失极小,显存减半
# INT4:分组量化,显存降到四分之一,适合消费级部署

# 用 bitsandbytes 加载量化模型示例
from transformers import BitsAndBytesConfig, AutoModelForCausalLM

quant_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype="float16",
)
model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen2.5-7B",
    quantization_config=quant_config,
)

量化不是越激进越好。如果你的场景是代码生成或者数学推理,对精度敏感,建议用 INT8;如果只是客服问答或者文案生成,INT4 完全够用。

KV Cache:解码阶段的隐形开销

大模型生成第二个 token 时,理论上需要把前面所有 token 重新过一遍注意力。KV Cache 把每一层的 Key 和 Value 向量缓存下来,生成新 token 时只算新 token 的 Q,和缓存的 K/V 做注意力,不用重算历史。

但 KV Cache 不是免费的。它的大小随上下文长度线性增长:一个 7B 模型,32 层、每头 128 维、32 头,缓存 4096 个 token 就要占好几个 GB。上下文越长,KV Cache 占得越多,多并发时显存直接爆掉。

KV Cache 的优化方向
  • 分页管理像操作系统虚拟内存一样把 KV Cache 分成块,消除碎片。
  • 量化 KV把 KV 也量化到 INT8,进一步省显存。
  • 滑动窗口只保留最近 N 个 token 的缓存,长上下文场景可控。

vLLM 与 PagedAttention

vLLM 是目前最流行的开源推理框架。它的核心创新是 PagedAttention:把 KV Cache 像操作系统的虚拟内存一样分页管理。每个请求的 KV Cache 不必连续存放,按需分配物理块,逻辑上连续就行。

# 用 vLLM 启动一个 OpenAI 兼容服务
# 安装:pip install vllm
# 启动:
# python -m vllm.entrypoints.openai.api_server \
#   --model Qwen/Qwen2.5-7B \
#   --quantization bitsandbytes \
#   --max-model-len 8192 \
#   --gpu-memory-utilization 0.9

# 调用和 OpenAI API 完全兼容
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy")
resp = client.chat.completions.create(
    model="Qwen/Qwen2.5-7B",
    messages=[{"role":"user","content":"你好"}],
)

PagedAttention 解决了 KV Cache 的显存碎片问题。在传统方式下,每个请求预分配最大长度的连续显存,实际用不完就浪费;分页后按需分配,显存利用率从百分之三四十提到百分之九十以上。

连续批处理与调度

除了显存,显卡的算力利用率也是问题。如果一次只处理一个请求,GPU 大量算力空闲。连续批处理(Continuous Batching)就是把不同用户的请求动态拼到一批里,一个请求做完了立刻塞下一个,GPU 永远跑满。

技术解决的问题效果
权重量化权重显存大显存减半到四分之一
KV Cache避免重算历史解码提速 10 倍以上
PagedAttentionKV 显存碎片显存利用率翻倍
连续批处理GPU 算力空闲吞吐量翻几倍