跳转至

第17章 §03 · 服务与批处理 · 讲解稿

承接: Ch17 §02 架构 → §03 服务部署 篇幅: ~4000 字


一 · 一句话总览

LLM 服务 = 把模型变成可靠 API。vLLM / SGLang / TensorRT-LLM / TGI 4 大引擎, PagedAttention + 连续批处理 让吞吐量提升 10-24×。


二 · 服务引擎 4 大家族

2.1 vLLM (UC Berkeley)

核心: PagedAttention (类 OS 虚拟内存)

from vllm import LLM, SamplingParams

llm = LLM(
    model="meta-llama/Llama-3-70B-Instruct",
    tensor_parallel_size=4,
    gpu_memory_utilization=0.9,
    quantization="awq",
    max_model_len=8192,
)

prompts = ["Hello, my name is", "The future of AI is"]
outputs = llm.generate(prompts, SamplingParams(temperature=0.7, max_tokens=100))

特性: - PagedAttention: KV 分块, 解决碎片 - 连续批处理: 每步加入新请求 - CUDA Graph: 减少 kernel launch 开销

2.2 SGLang (Stanford)

核心: RadixAttention + DSL (前端语言)

import sglang as sgl

@sgl.function
def multi_turn(s, user_q):
    s += sgl.system("You are a helpful assistant.")
    s += sgl.user(user_q)
    s += sgl.assistant(sgl.gen("answer", max_tokens=100))

runtime = sgl.Runtime(model="meta-llama/Llama-3-8B")
state = multi_turn.run(user_q="What is AI?", runtime=runtime)
print(state["answer"])

优势: 前端 DSL 让复杂 prompt 编程简单, RadixAttention 让 prefix 共享。

2.3 TensorRT-LLM (NVIDIA)

特性: - 极致性能: NVIDIA 官方, 完整 GPU 利用 - In-flight batching / Continuous batching - FP8 / INT4 量化

from tensorrt_llm import LLM

llm = LLM(model="meta-llama/Llama-3-8B")
outputs = llm.generate(["Hello"])

2.4 TGI (HuggingFace)

特性: 易部署, Rust 写, 支持多模型。

2.5 LMDeploy (上海AI Lab)

特性: 中文 LLM 优化, 高吞吐。


三 · 连续批处理 (Continuous Batching)

3.1 传统批处理

请求 A (1024 token) + 请求 B (128 token)
→ 等 A 完成 (1024 步), B 早完成也在等
→ 总耗时 1024 步, 浪费 896 步

3.2 连续批处理

请求 A 处理 500 步, B 已完成
→ B 的 GPU 让给 C, A 继续
→ 总耗时 ~500 + 1024/2 ≈ 1000 步, 节省 ~25%

3.3 性能对比

引擎 静态批处理 连续批处理
vLLM 1× 24×
SGLang 1× 20×
TGI 1× 15×
TensorRT-LLM 1× 20×

四 · Speculative Decoding

4.1 核心思想

小模型草拟 + 大模型并行验证

草拟: [t1, t2, t3, t4, t5] (小模型, 1 ms)
验证: 1 次 forward 算 5 个位置概率 (大模型, 2 ms)
接受率 70%: 平均接受 3.5 个, 节省 60% 时间

4.2 主流方案

方案 草拟模型 适用
Self-Speculative 模型本身 (退出层) 通用
Draft Model 独立小模型 7B/70B 配 1B
Medusa 多头并行预测 Llama 专属
EAGLE 特征层预测 SOTA 2024

4.3 Medusa 示例

from medusa import MedusaModel

model = MedusaModel.from_pretrained(
    "FasterDecoding/medusa-1.0-vicuna-7b-v1.5",
    base_model="lmsys/vicuna-7b-v1.5",
)
output = model.generate("Hello", max_tokens=100)

五 · Prompt Caching

5.1 原理

缓存相同前缀的 KV: - System prompt 10K+ token 时, 节省 80% 成本 - Anthropic / OpenAI 均支持

5.2 Anthropic Prompt Caching

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "你是专业的代码助手...",
            "cache_control": {"type": "ephemeral"}  # 缓存标记
        }
    ],
    messages=[{"role": "user", "content": "写一个 Hello World"}]
)

5.3 5 大缓存策略

  1. Prefix cache: 相同前缀复用
  2. Semantic cache: 相似 query 复用
  3. KV cache: 完整 KV 存储
  4. CDN: 模型 + 响应全局缓存
  5. Browser cache: 客户端 (WebLLM)

六 · 调度策略

6.1 FCFS vs Priority

  • FCFS: 简单, 不公平 (长 prompt 拖慢)
  • Priority: 用户分等级 (付费 > 免费)
  • Fair: 保证 SLA

6.2 Prefill vs Decode 分离

  • Prefill: 长 prompt 一次性 forward (慢, 大 batch 友好)
  • Decode: 逐 token 生成 (latency-bound)

DistServe (NSDI 2024): 分离 Prefill + Decode 到不同 GPU, 互不干扰。

6.3 SLO-aware 调度

  • P99 latency 目标
  • 动态 batching + priority queue
  • Kubernetes + 自定义调度器

七 · 监控与可观测性

7.1 关键指标

指标 含义 目标
TTFT Time To First Token < 500 ms
TPOT Time Per Output Token < 50 ms
Throughput tokens/s/GPU 越高越好
GPU Util GPU 利用率 > 70%
Queue Length 等待请求数 < 100

7.2 工具

  • Prometheus + Grafana: 通用
  • vLLM metrics: 内置
  • Langfuse: LLM 专属 (含 trace)
  • Phoenix (Arize): Eval + Trace
  • Helicone: API 网关层

八 · 一句话总结

LLM 服务 = 引擎 + 批处理 + Speculative + Cache + 调度 + 监控。vLLM / SGLang 是工业首选, 连续批处理 + Speculative Decoding + Prompt Caching 三件套让 LLM 服务吞吐 + 延迟双优。