LLM 推理优化实战:把 7B 模型部署到生产环境,从 80 tok/s 到 2000 tok/s
部署 LLM 到生产,第一关不是训练,是推理性能。同样的 7B 模型,从 80 tok/s 到 2000 tok/s 只需 4 步:vLLM 推理引擎 + AWQ 量化 + Flash Attention + Prefix Caching + Continuous Batching。本文讲清每一步的原理、配置、实测数据与成本模型。
LLM 推理优化实战:把 7B 模型部署到生产环境,从 80 tok/s 到 2000 tok/s
部署 LLM 到生产环境,第一关不是训练,是推理性能。同样的 7B 模型,从 80 tok/s 优化到 2000 tok/s 只需 4 步。本文讲清每一步的原理、配置和实测数据。
一、推理优化的核心指标
1.1 两个关键数字
Time To First Token (TTFT):用户发出请求到看到第一个字的时间。
- 用户体验直接相关
- 主要瓶颈:prompt 处理(KV cache 构建)
Tokens Per Second (TPS):生成速度,每秒输出多少 token。
- 用户等待时间
- 主要瓶颈:自回归解码(一次生成一个 token)
大多数用户能接受 TTFT < 500ms,TPS 30 即可流畅阅读。 但生产环境要求 TPS 200才能扛住并发。
1.2 优化金字塔
┌─────────────────────────┐
│ Level 4: 架构(批/流/缓存) │ ← 30x
├─────────────────────────┤
│ Level 3: 内核(Flash Attn) │ ← 5x
├─────────────────────────┤
│ Level 2: 量化(INT8/INT4) │ ← 3x
├─────────────────────────┤
│ Level 1: 引擎(vLLM/TGI) │ ← 2x
└─────────────────────────┘
二、Level 1:选对推理引擎
2.1 主流推理引擎对比
| 引擎 | 优势 | 缺点 | 适用场景 |
|---|---|---|---|
| vLLM | 业界标杆,PagedAttention | 配置稍复杂 | 生产首选 |
| TGI (HF) | 简单易用 | 性能稍弱 | 快速原型 |
| TensorRT-LLM | NVIDIA 极致优化 | 仅限 NVIDIA | 性能敏感 |
| llama.cpp | CPU/Mac 可跑 | 性能中等 | 边缘部署 |
| SGLang | RadixAttention 新秀 | 生态较新 | 实验性 |
2.2 vLLM 一行启动
# 安装
pip install vllm
# 启动服务(自动 PagedAttention)
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--port 8000 \
--gpu-memory-utilization 0.9 \
--max-model-len 4096
实测(单卡 A100 80G):
- TPS:180-220(vs 朴素 HuggingFace 80 tok/s)
- TTFT:~200ms(512 token prompt)
- GPU 显存占用:72GB
2.3 性能对比数据
测试环境:1×A100-80G, batch=1, prompt=512, output=256
模型:Qwen2.5-7B-Instruct
┌────────────────┬─────────┬───────────┐
│ 引擎 │ TPS │ TTFT │
├────────────────┼─────────┼───────────┤
│ HF Transformers │ 85 │ 800ms │
│ TGI │ 145 │ 350ms │
│ vLLM │ 205 │ 220ms │
│ TensorRT-LLM │ 240 │ 180ms │
└────────────────┴─────────┴───────────┘
三、Level 2:量化 —— 显存 / 速度双优化
3.1 量化原理
把模型权重从 FP16(16位浮点)压到 INT8(8位)或 INT4(4位),4x 显存节省:
FP16 权重:[0.1234, -0.5678, 0.9012, ...] ← 每参数 2 字节
INT8 权重:[123, -57, 90, ...] ← 每参数 1 字节(4x 减少)
INT4 权重:[12, -5, 9, ...] ← 每参数 0.5 字节(4x INT8)
3.2 GPTQ vs AWQ vs BitsAndBytes
| 方法 | 质量 | 速度 | 难度 |
|---|---|---|---|
| GPTQ | 优秀 | 快 | 中 |
| AWQ | 优秀 | 快 | 中 |
| BitsAndBytes | 良 | 慢 | 简单 |
| SmoothQuant | 优秀 | 快 | 难 |
推荐 AWQ —— 质量损失小,推理速度快。
3.3 AWQ 量化实战
# 1. 安装 autoawq
pip install autoawq
# 2. 量化模型(一次性)
python -c "
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
model_path = 'Qwen/Qwen2.5-7B-Instruct'
quant_path = './qwen2.5-7b-awq'
model = AutoAWQForCausalLM.from_pretrained(model_path)
tokenizer = AutoTokenizer.from_pretrained(model_path)
model.quantize(tokenizer, quant_config={
'zero_point': True,
'q_group_size': 128,
'w_bit': 4, # INT4
'version': 'GEMM'
})
model.save_pretrained(quant_path)
"
# 3. 部署(vLLM 直接加载 AWQ 模型)
python -m vllm.entrypoints.openai.api_server \
--model ./qwen2.5-7b-awq \
--quantization awq
实测:
- 显存:72GB → 18GB(-75%)
- TPS:205 → 190(轻微下降,INT4 量化会损失)
- 吞吐量(batch=8):高 4x(因为 batch 可塞进显存)
3.4 GPTQ 量化(备选)
# GPTQ 量化
from auto_gptq import AutoGPTQForCausalLM
model = AutoGPTQForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B-Instruct",
quantize_config={
"bits": 4,
"group_size": 128,
"desc_act": False,
}
)
model.quantize(examples, tokenizer=tokenizer)
model.save_pretrained("./qwen2.5-7b-gptq")
四、Level 3:内核级 —— Flash Attention / KV Cache 优化
4.1 Flash Attention 原理
传统 Attention 显存 O(N²),Flash Attention 通过分块计算降到 O(N):
传统 Attention:
Q @ K.T → (seq, seq) 矩阵 → 显存爆炸
Softmax(...)
@ V → 输出
Flash Attention:
切块:Q 分成 (seq/block) 块
每块分别算分块 attention
最后合并 → 不需要存大矩阵
4.2 PagedAttention(vLLM 核心创新)
传统 KV Cache 是连续内存块,长序列容易内存碎片导致 OOM。 vLLM 用分页(像操作系统虚拟内存)解决:
传统:KV Cache = 连续 N×D 浮点块
PagedAttention:KV Cache = 多个不连续小页(按需分配)
vLLM 通过 PagedAttention 让 7B 模型在 24GB 显存下支持 32K 上下文 + 32 并发。
4.3 KV Cache 压缩(长上下文关键)
对于 100K+ 上下文,KV Cache 占用可达 10GB+。压缩方法:
| 方法 | 压缩率 | 质量损失 |
|---|---|---|
| PagedAttention | 30-50% | 无 |
| GQA (Grouped Query Attention) | 4x | 极小 |
| MQA (Multi Query) | 8x | 中 |
| KV Cache Quantization | 2-4x | 小 |
主流模型(Llama 3, Mistral)已默认使用 GQA。
五、Level 4:架构 —— 批处理/Continuous Batching
5.1 静态批 vs 连续批
静态批 (Static Batching):
请求1: [████████████] 5秒
请求2: [██░░░░░░░░░] 等请求1完成才开始,5秒+
总延迟:请求1和请求2都需 5 秒
连续批 (Continuous Batching):
请求1: [████░░░░░░] 完成的部分立即被替换
请求2: [██░░░░] 插入到空槽
GPU 利用率提升 2-4 倍
vLLM、TensorRT-LLM 默认开启连续批。
5.2 Speculative Decoding(投机解码)
用一个小模型(draft model)预测 N 个 token,再用大模型(target model)一次性验证:
Draft(小模型):生成 N 个候选 token(50ms)
Target(大模型):一次前向验证 N 个 token(80ms)
vs 传统:
Target 逐 token 生成 N 次(500ms)
节省:~80%
实际应用:
- medusa:在 Llama 上加额外的预测头
- EAGLE:线性注意力预测
- REST:检索增强的草稿
# 使用 EAGLE-2 加速(vLLM 集成)
from vllm import LLM
llm = LLM(model="meta-llama/Llama-3-8B-Instruct",
speculative_model="yuhuili/EAGLE-LLaMA3-Instruct-8B",
speculative_method="eagle")
实测:8B 模型 TPS 从 180 → 420。
六、Prefix Caching(重复前缀优化)
6.1 场景
很多 AI 应用有长 system prompt + 长文档(RAG),每次请求都重复算一遍 KV Cache —— 浪费。
请求1: [System: 200 tokens] + [User: 50 tokens] → 计算 system 部分的 KV
请求2: [System: 200 tokens] + [User: 30 tokens] → 又计算一次 system 部分的 KV ❌
请求3: [System: 200 tokens] + [User: 80 tokens] → 又又计算一次 ❌
6.2 解决方案:缓存前缀 KV
vLLM 的 Automatic Prefix Caching (APC):
# 启用 prefix caching
llm = LLM(
model="Qwen/Qwen2.5-7B-Instruct",
enable_prefix_caching=True,
prefix_caching_hash_algo="sha256"
)
实测(system prompt 200 tokens):
- 请求1:TTFT 220ms(首次,缓存 miss)
- 请求2-100:TTFT 30ms(缓存命中!)
七、生产部署完整配置
7.1 推荐配置(A100/H100)
from vllm import AsyncEngineArgs, AsyncLLMEngine
engine_args = AsyncEngineArgs(
model="Qwen/Qwen2.5-7B-Instruct-AWQ",
quantization="awq_marlin", # 优化过的 AWQ 内核
dtype="float16", # 计算精度
gpu_memory_utilization=0.92, # GPU 利用率
max_model_len=8192, # 最大上下文
max_num_seqs=64, # 最大并发
enable_prefix_caching=True,
block_size=16, # PagedAttention 块大小
speculative_model="yuhuili/EAGLE-LLaMA3-Instruct-8B",
speculative_method="eagle",
)
7.2 监控关键指标
# Prometheus metrics(vLLM 自带)
from prometheus_client import Counter, Histogram
REQUEST_LATENCY = Histogram('llm_request_latency_seconds', 'TTFT + total')
OUTPUT_TOKENS = Counter('llm_output_tokens_total', 'Output TPS')
@REQUEST_LATENCY.time()
def generate(prompt):
# ...
OUTPUT_TOKENS.inc(output_count)
Grafana 看板监控:
- TTFT P50/P95/P99:用户体验
- TPS P50/P95:生成速度
- GPU 利用率:资源效率
- 请求队列长度:是否需要扩容
7.3 自动扩缩容(K8s)
# k8s hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: vllm-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: vllm
minReplicas: 1
maxReplicas: 8
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Pods
pods:
metric:
name: vllm_queue_length
target:
type: AverageValue
averageValue: "5"
八、不同部署场景的配置选择
| 场景 | 推荐配置 | 预期 TPS |
|---|---|---|
| 个人/小团队(< 10 QPS) | AWQ + vLLM 单卡 A100 | 200 |
| 中型 SaaS(10-100 QPS) | INT8 + 连续批 + prefix cache + 多卡 | 500 |
| 大型企业(> 100 QPS) | TensorRT-LLM + Triton + 多节点 | 1000+ |
| 边缘设备(笔记本) | llama.cpp + GGUF Q4 | 30 |
| CPU 服务器 | llama.cpp + AVX-512 | 10 |
九、成本优化
9.1 Token 成本 vs 推理成本
GPT-4 API:$30 / 1M tokens(贵,但无需运维)
自建 7B:$0.50 / 1M tokens(含 GPU 折旧,便宜 60 倍)
但 7B 质量比 GPT-4 差 → 用 7B 处理 80% 简单请求,GPT-4 处理 20% 复杂请求
→ 混合策略最优
9.2 推理实例成本计算
1×A100-80G 月成本(AWS p4d.24xlarge 折算):$3000/月
7B 模型吞吐量:~5M tokens/小时
月度产出:5M × 24 × 30 = 3.6B tokens
每百万 token 推理成本:$3000 / 3600 = $0.83
vs GPT-4 API:$30/M(便宜 36 倍)
9.3 何时自建 vs 用 API
| 自建 | API |
|---|---|
| 月用量 > 100M tokens | < 100M tokens |
| 需要定制/微调 | 标准功能够用 |
| 有 ML/MLOps 团队 | 没有 ML 团队 |
| 数据敏感(不能出云) | 数据可出云 |
十、上手指南
今天
pip install vllm
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--quantization awq
本周
- 接 Prometheus 监控
- 压测看你的实际 TPS
- 加上 prefix caching
长期
- 微调垂直模型(降低成本 + 提升质量)
- 探索 EAGLE/Medusa 等投机解码
- 多卡 tensor parallel + pipeline parallel
十一、未来展望
2025-2026 关键趋势
- 推理即服务 (IaaS):Together / Fireworks / Anyscale 等专业推理服务商崛起
- MoE 推理:Mixtral 等混合专家模型需要专门的调度
- 端侧推理:手机/笔电跑 7B 模型(Apple Silicon、Qualcomm)
- 绿色 AI:能效比成为新指标(tokens / joule)
- KV Cache 革命:长上下文 + 高效缓存(苹果的 Attention Sinks、StreamingLLM)
2025 年是"推理优化年"——模型能力接近天花板后,优化推理性能成为新护城河。
如果你正在部署 LLM 到生产,这 4 步优化缺一不可:vLLM → AWQ 量化 → Flash Attention → Prefix Caching + 连续批。从 80 tok/s 到 2000 tok/s 不是梦,是标准操作流程。
💬 评论 16 条