上一篇我们打好了地基:推理的 Prefill/Decode 两阶段、显存账本(权重 + KV Cache + 激活值)、四个核心指标(TTFT / TPOT / 吞吐 / 显存)。这一篇进入核心提升区——学完这一层,你才真正看懂 vLLM 那些参数背后到底在干嘛。
这一篇讲三件事,都是 vLLM 这类推理框架的"命根子":
量化:怎么把模型"瘦身",省显存、提速度
KV Cache:为什么每次推理都要存一堆"中间记忆",以及怎么省
吞吐优化:怎么让一张卡同时服务更多人、每个请求更快
文章目录
- 01 量化:给模型"瘦身"
- 为什么需要量化?
- FP16 → INT8 → INT4,各掉多少精度?
- 三种主流量化方法
- ① GPTQ —— 逐层"事后"量化(Post\-Training Quantization)
- ② AWQ —— 按"重要程度"加权量化
- ③ SmoothQuant —— 把"难量化的"转移走
- 一张表看懂三种方法
- 02 KV Cache:推理的"中间记忆"
- 什么是 KV Cache?
- 为什么 KV Cache 这么占显存?
- PagedAttention:vLLM 的"命根子"
- GQA / MQA:给注意力"减配"
- 03 吞吐优化:一张卡服务更多人
- Continuous Batching:别等最慢的那个人
- 投机解码(Speculative Decoding):小模型起草,大模型校验
- 04 一页纸总结
- 05 学完你能看懂 vLLM 的什么?
01 量化:给模型"瘦身"
为什么需要量化?
回想上一篇的显存账本:权重显存 = 参数量 × 每参数字节数。
FP32 = 4 字节
FP16 / BF16 = 2 字节
INT8 / FP8 = 1 字节
INT4 / FP4 = 0.5 字节
一个 70B 模型:
| 精度 | 每参数字节 | 权重显存 |
|---|---|---|
| FP16 | 2 | 140 GB |
| INT8 | 1 | 70 GB |
| INT4 | 0.5 | 35 GB |
同样是 70B,从 FP16 压到 INT4,显存直接砍掉 75%。这决定了你能不能把它塞进一张卡,或者能不能省下卡数。
量化 = 用更少的比特数去表示权重。就像一张照片从 4K 压到 1080p——体积小了,但画质会有损失。
FP16 → INT8 → INT4,各掉多少精度?
| 精度 | 显存 | 精度损失 | 适用场景 |
|---|---|---|---|
| FP16/BF16 | 基准 | 无 | 追求极致精度,显存够用 |
| INT8 | 减半 | 很小(通常 <1% 质量损失) | 大多数生产场景,性价比最高 |
| INT4 | 减 75% | 明显(复杂任务可能掉 1-3%+) | 显存紧张、端侧/单卡部署 |
关键认知:精度损失不是均匀的。简单任务(摘要、翻译)几乎无感,复杂推理(数学、代码、长链推理)损失更明显。所以选精度要"看任务下菜"。
三种主流量化方法
① GPTQ —— 逐层"事后"量化(Post-Training Quantization)
做法:模型训练完,拿一小批校准数据,逐层把权重压到 INT4/INT8,同时用误差补偿把每层的量化误差尽量抹平。
原理:不是简单粗暴地四舍五入,而是量化完一层后,用"最小化输出误差"的方式微调这一层的权重,让量化前后的输出尽量一致。
适用:离线一次性量化。量化过程较慢(要跑校准数据),但量完就固定了,推理时零额外开销。
代表:AutoGPTQ、GPTQ-for-LLaMa。
② AWQ —— 按"重要程度"加权量化
做法:也是事后量化,但核心洞察是——权重不是一样重要的。只有少数"重要通道"(对应激活值大的通道)对精度影响大,其余大部分可以大胆量化。
原理:先分析校准数据,找出哪些通道的激活值大(重要),对这些通道保留更高精度(少量化一点),其余通道狠量。相当于"重点保护关键少数"。
适用:比 GPTQ 在同等精度下通常质量更好,推理速度也快;同样适合离线量化。
代表:vLLM 内置支持 AWQ。
③ SmoothQuant —— 把"难量化的"转移走
做法:针对**激活值(activation)**难量化的问题。权重好量化,但激活值波动大、有离群值,直接量化会爆。
原理:把激活值里的"尖峰"通过一个缩放系数迁移到权重上——让激活值变得平滑好量化,代价是权重稍微难一点(但权重好量)。两边都好量了,就能用 INT8 同时量化权重和激活。
适用:W8A8(权重和激活都 INT8)场景,适合追求推理加速(不只省显存,还提速)的部署。
一张表看懂三种方法
| 方法 | 量化对象 | 核心思想 | 适用场景 | 代表工具 |
|---|---|---|---|---|
| GPTQ | 权重为主 | 逐层误差补偿 | 离线量化、INT4 省显存 | AutoGPTQ |
| AWQ | 权重 | 保护重要通道 | 离线量化、质量优先 | vLLM 内置 |
| SmoothQuant | 权重+激活 | 激活尖峰转移给权重 | W8A8、追求推理加速 | vLLM / TensorRT-LLM |
一句话:GPTQ 是"逐层找补",AWQ 是"重点保护",SmoothQuant 是"把刺拔掉再量化"。
02 KV Cache:推理的"中间记忆"
什么是 KV Cache?
上一篇讲过注意力机制:每个 token 都要和之前所有 token 算注意力。如果每次都重新算一遍前面所有 token 的 Key/Value,那代价是 O(n²),慢到爆炸。
KV Cache = 把已经算过的 Key 和 Value 缓存下来,新 token 来了直接复用,不用重算。
它就是你上一篇显存账本里的"第二项",随上下文长度 × 并发数增长,是推理显存的大头。
为什么 KV Cache 这么占显存?
公式(上一篇讲过):
KV Cache 大小 ≈ 2(K 和 V)× 层数 × hidden_size × 上下文长度 × 精度字节 × 并发数一个 7B 模型,8K 上下文、8 并发,KV Cache 就能到32GB——比权重(14GB)还大。这就是为什么长上下文 + 高并发是显存杀手。
PagedAttention:vLLM 的"命根子"
问题:传统推理框架给每个请求预先分配一整块连续显存(像数组)。但每个请求实际用多少 token 是动态的——预分配多了浪费,少了不够。显存碎片化严重。
PagedAttention 的核心洞察:把 KV Cache 切成固定大小的小块(page),像操作系统分页一样,按需分配。请求用多少就分配多少块,块可以不连续地散落在显存各处。
为什么省显存?
按需分配:不再预分配整块,利用率大幅提升(可到 90%+)
消除碎片:小块可以散落存放,不浪费边角显存
共享:多个请求如果前缀相同(比如系统提示词一样),可以共享同一批 KV Cache 块,进一步省显存
一句话:PagedAttention 把 KV Cache 从"整块预分配"变成"按页按需分配",像内存分页一样,让显存利用率从 60% 拉到 90%+。这就是 vLLM 快、省显存的核心秘密。
GQA / MQA:给注意力"减配"
注意力计算里有多个"头"(multi-head attention)。每个头都有自己的 K、V,KV Cache 也就跟着翻倍。
MHA(多头注意力):每个头都独立存 K、V → KV Cache 最大。
GQA(分组查询注意力):把多个查询头共享同一组K、V 头。比如 32 个查询头只配 8 个 KV 头 → KV Cache 直接砍到 1/4。
MQA(多查询注意力):更极端,所有查询头共享 1 个KV 头 → KV Cache 最小,但质量略有损失。
| 方法 | KV 头数 | KV Cache | 质量 |
|---|---|---|---|
| MHA | 全部(如 32) | 基准(最大) | 最好 |
| GQA | 分组(如 8) | 减到 1/4 | 几乎无损 |
| MQA | 1 个 | 最小 | 略降 |
现状:现在的模型(包括 Llama 3、Mistral、DeepSeek)普遍用GQA——在几乎不掉质量的前提下,把 KV Cache 砍掉一大截。这也是为什么同样上下文,新模型的 KV Cache 比老模型小得多。
03 吞吐优化:一张卡服务更多人
Continuous Batching:别等最慢的那个人
问题:传统批处理(static batching)是"一整车一起出发"——一批请求必须全部完成才处理下一批。如果批里有个超长请求,其他短请求得干等,GPU 大量空闲。
Continuous Batching(连续批处理):谁先结束谁先走,随时有新请求就插进来。GPU 上永远有活干,不空转。
一个请求的 token 生成完了 → 立即腾出位置,让新请求进来
短请求不用等长请求,GPU 利用率大幅提升
一句话:Continuous Batching 让 GPU 像"流水线"而不是"班车",吞吐量通常能提升 2-10 倍。这是 vLLM 吞吐高的另一大秘密。
投机解码(Speculative Decoding):小模型起草,大模型校验
问题:Decode 阶段是逐字串行的,每生成一个 token 都要完整跑一遍大模型,而且 Decode 受带宽限制(不是算力),GPU 算力大量闲置。
投机解码的核心思想:让一个快的小模型先草拟接下来几个 token,大模型一次性并行校验这几个 token 对不对。
小模型(draft model)起草 3-5 个候选 token
大模型(target model)一次性校验,如果都对就一次接受多个 token
对的部分直接采纳,错的部分从错处重新起草
效果:一次校验能"批发"多个 token,Decode 速度提升 2-3 倍(取决于接受率)。因为小模型快、大模型省了多次串行调用。
一句话:投机解码用"小模型猜、大模型验"的方式,把串行的逐字生成变成批量的并行校验,是当前最火的 Decode 加速手段。
04 一页纸总结
L2 推理优化三件套: ① 量化(省显存) FP16 → INT8(减半,几乎无损)→ INT4(减 75%,有损) GPTQ:逐层误差补偿(离线) AWQ :保护重要通道(离线,质量好) SmoothQuant:激活尖峰转移给权重(W8A8,提速) ② KV Cache(省显存) PagedAttention:KV Cache 按页按需分配 → 显存利用率 60%→90%+ GQA/MQA:多个查询头共享 KV 头 → KV Cache 砍到 1/4 甚至更小 ③ 吞吐(提速度) Continuous Batching:谁先完谁先走 → 吞吐提升 2-10 倍 投机解码:小模型起草 + 大模型校验 → Decode 提速 2-3 倍05 学完你能看懂 vLLM 的什么?
现在回头看你 vLLM 配置里那些参数:
| vLLM 参数 | 对应本篇知识 |
|---|---|
--quantization awq / gptq | 量化方法选型(AWQ 质量好 / GPTQ 省显存) |
--kv-cache-dtype fp8 | KV Cache 也用低精度省显存 |
--gpu-memory-utilization | 给 KV Cache 预留多少显存(PagedAttention 按需用) |
--max-num-seqs | 并发序列数上限(影响 Continuous Batching 效果) |
--speculative-model | 投机解码的起草小模型 |
--enable-prefix-caching | 前缀共享 KV Cache(PagedAttention 的共享块) |
一句话:这一层学完,vLLM 那些参数不再是"玄学",而是每个都能对应到一个具体的优化原理——你知道调它是在省显存、提吞吐还是加速度。