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-LLMNVIDIA 极致优化仅限 NVIDIA性能敏感
llama.cppCPU/Mac 可跑性能中等边缘部署
SGLangRadixAttention 新秀生态较新实验性

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+。压缩方法:

方法压缩率质量损失
PagedAttention30-50%无
GQA (Grouped Query Attention)4x极小
MQA (Multi Query)8x中
KV Cache Quantization2-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 单卡 A100200
中型 SaaS(10-100 QPS)INT8 + 连续批 + prefix cache + 多卡500
大型企业(> 100 QPS)TensorRT-LLM + Triton + 多节点1000+
边缘设备(笔记本)llama.cpp + GGUF Q430
CPU 服务器llama.cpp + AVX-51210

九、成本优化

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 关键趋势

  1. 推理即服务 (IaaS):Together / Fireworks / Anyscale 等专业推理服务商崛起
  2. MoE 推理:Mixtral 等混合专家模型需要专门的调度
  3. 端侧推理:手机/笔电跑 7B 模型(Apple Silicon、Qualcomm)
  4. 绿色 AI:能效比成为新指标(tokens / joule)
  5. KV Cache 革命:长上下文 + 高效缓存(苹果的 Attention Sinks、StreamingLLM)
2025 年是"推理优化年"——模型能力接近天花板后,优化推理性能成为新护城河。

如果你正在部署 LLM 到生产,这 4 步优化缺一不可:vLLM → AWQ 量化 → Flash Attention → Prefix Caching + 连续批。从 80 tok/s 到 2000 tok/s 不是梦,是标准操作流程。