推理优化 2026:投机解码、前缀缓存与分离式部署
推理优化 2026:投机解码、前缀缓存与分离式部署
同样一张卡,为什么别人的服务吞吐是你的 5 倍?差距不在模型,在推理引擎和优化手段。这篇讲清 2026 年主流的五种优化手段,并给 vLLM 实战部署配置。

一、先搞清楚:推理为什么慢
大模型推理是自回归的——一个 token 一个 token 往外蹦。每个 token 都要:
- 从显存加载模型权重(显存带宽瓶颈);
- 做矩阵运算;
- 读写 KV Cache。
关键认知:推理的瓶颈通常不是算力(FLOPS),而是显存带宽。你 GPU 利用率看着 100%,其实大部分时间在等数据搬运。
所以优化思路就两条:
- 减少重复计算(前缀缓存、投机解码);
- 提高硬件利用率(批处理、PD 分离、量化)。
二、五种优化手段

1. 投机解码(Speculative Decoding)
原理:
- 用一个小模型(草稿模型)快速生成 N 个候选 token;
- 大模型一次性并行验证这 N 个 token;
- 对的直接采纳,错的从第一个错的位置重新生成。
为什么快:大模型验证 N 个 token 的耗时 ≈ 生成 1 个 token 的耗时(并行),但小模型生成 N 个很便宜。
收益:通常 1.5-3x 加速,且输出质量完全不变(因为最终由大模型确认)。
关键前提:草稿模型要和大模型同分布(比如 Qwen2.5-0.5B 给 Qwen2.5-7B 做草稿),否则命中率低反而更慢。
2. 前缀缓存(Prefix Caching)
原理:把已计算的 KV Cache 缓存起来,下次遇到相同前缀直接复用,不做重复计算。
典型场景:
- System Prompt 很长(几 k token),每次请求都重复计算 → 缓存后省掉;
- 多轮对话:历史部分可复用;
- RAG:相同的文档片段被多次检索时。
收益:首 token 延迟(TTFT)大幅下降;命中率高时吞吐提升明显。
3. 连续批处理(Continuous Batching)
传统批处理:一批请求一起进来,必须等最慢的那个完成才能放新请求进来(队头阻塞)。
连续批处理:请求逐个完成、逐个补充,谁好了谁走,新请求随时插入。
收益:吞吐 2-5x,这是 vLLM 等现代框架的核心能力。
4. 分离式部署(PD 分离)
推理分两个阶段,特性完全不同:
| 阶段 | 特点 | 瓶颈 |
|---|---|---|
| Prefill(预填充) | 处理输入 prompt,可并行 | 算力密集 |
| Decode(解码) | 逐 token 生成 | 显存带宽密集 |
混在一起跑 = 两种负载互相干扰。分离式部署把两个阶段放到不同的卡/机器上,各自用最合适的硬件和并行策略。
收益:整体成本降 30%+,是大模型服务规模化的关键架构。
5. 量化
| 精度 | 显存 | 速度 | 精度损失 |
|---|---|---|---|
| FP16 | 基准 | 基准 | 无 |
| FP8 | 减半 | 快 | 极小 |
| INT8 | 减半 | 快 | 小 |
| INT4 (GPTQ/AWQ) | 1/4 | 快 | 可接受 |
建议:7B 模型 16G 显存跑 FP16 没问题;要跑 70B 就得量化(AWQ/GPTQ INT4)。
三、vLLM 实战部署(2026 主流)
vLLM 是目前最常用的推理引擎,天然支持连续批处理 + PagedAttention + 前缀缓存。
3.1 安装
pip install vllm
3.2 基础启动(OpenAI 兼容 API)
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--served-model-name qwen2.5 \
--host 0.0.0.0 \
--port 8000 \
--gpu-memory-utilization 0.9 \
--max-model-len 8192 \
--enable-prefix-caching
3.3 开启投机解码
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--speculative-model Qwen/Qwen2.5-0.5B-Instruct \
--num-speculative-tokens 5 \
--enable-prefix-caching
--num-speculative-tokens是每次草稿的 token 数,通常 3-5。
3.4 多卡并行
# 张量并行(单模型拆到多卡)
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-32B-Instruct \
--tensor-parallel-size 4
3.5 量化启动
# AWQ 量化模型
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct-AWQ \
--quantization awq
四、调用测试
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""调用 vLLM 的 OpenAI 兼容接口"""
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed", # vLLM 不需要 key
)
resp = client.chat.completions.create(
model="qwen2.5",
messages=[
{"role": "system", "content": "你是一个助手。"},
{"role": "user", "content": "用一句话解释什么是投机解码。"},
],
temperature=0.1,
max_tokens=200,
)
print(resp.choices[0].message.content)
print(f"\n[用量] prompt={resp.usage.prompt_tokens}, "
f"completion={resp.usage.completion_tokens}")
输出:
投机解码是用小模型快速生成候选 token、再由大模型并行验证的加速技术,
能在不损失输出质量的前提下显著提升生成速度。
[用量] prompt=24, completion=48
五、性能压测方法
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
简单压测:并发请求,测吞吐(tokens/s)与延迟
依赖:pip install openai
"""
import time
import threading
from openai import OpenAI
from concurrent.futures import ThreadPoolExecutor
client = OpenAI(base_url="http://localhost:8000/v1", api_key="x")
CONCURRENCY = 16
N_REQUESTS = 64
def one(i):
t0 = time.time()
r = client.chat.completions.create(
model="qwen2.5",
messages=[{"role": "user",
"content": f"请简短介绍一下人工智能(第{i}次)。"}],
max_tokens=150, temperature=0.7,
)
dt = time.time() - t0
return dt, r.usage.completion_tokens
def main():
t0 = time.time()
with ThreadPoolExecutor(max_workers=CONCURRENCY) as pool:
results = list(pool.map(one, range(N_REQUESTS)))
total = time.time() - t0
total_tokens = sum(t for _, t in results)
latencies = [d for d, _ in results]
latencies.sort()
print(f"总请求:{N_REQUESTS},并发:{CONCURRENCY}")
print(f"总耗时:{total:.2f}s")
print(f"吞吐 :{total_tokens/total:.1f} tokens/s")
print(f"QPS :{N_REQUESTS/total:.2f}")
print(f"平均延迟:{sum(latencies)/len(latencies):.2f}s")
print(f"P95延迟:{latencies[int(len(latencies)*0.95)]:.2f}s")
if __name__ == "__main__":
main()
典型输出(单卡 4090,7B):
总请求:64,并发:16
总耗时:18.42s
吞吐 :892.3 tokens/s
QPS :3.47
平均延迟:4.51s
P95延迟:6.12s
优化前后对比(同一张卡):
| 配置 | 吞吐(tokens/s) | 提升 |
|---|---|---|
| 基础(HF transformers) | ~120 | 基准 |
| vLLM(连续批处理) | ~610 | 5.1x |
| vLLM + 前缀缓存 | ~780 | 6.5x |
| vLLM + 投机解码 | ~890 | 7.4x |
六、落地建议
- 优先上 vLLM(或 SGLang),光是连续批处理就有数倍提升,零成本;
- System Prompt 固定时必开前缀缓存——收益巨大且无副作用;
- 投机解码要看命中率:草稿模型不合适反而会变慢,先小流量验证;
- 量化按需:显存够就别量化(精度最好),显存不够优先 AWQ;
- PD 分离是规模化方案:日活请求量大时才需要,小规模别过度设计;
- 监控三指标:TTFT(首 token 延迟)、TPOT(每 token 时间)、吞吐。
七、选型速查
| 场景 | 推荐方案 |
|---|---|
| 单机 demo / 开发 | Ollama(最简单) |
| 生产 API 服务 | vLLM(连续批处理 + 前缀缓存) |
| 极致低延迟 | vLLM + 投机解码 |
| 超大规模 | vLLM + PD 分离 + 多机并行 |
| CPU / 边缘 | llama.cpp + GGUF 量化 |
小结
- 推理瓶颈通常是显存带宽,不是算力;
- 五大手段:投机解码、前缀缓存、连续批处理、PD 分离、量化;
- vLLM 是生产首选,开箱即有连续批处理(5x+);
- 前缀缓存零成本收益大,固定 System Prompt 场景必开;
- 压测看三指标:TTFT、TPOT、吞吐。
环境:vLLM 0.6+ / Qwen2.5-7B / NVIDIA 4090 24G
浙公网安备 33010602011771号