跳到主要内容

模型服务与推理

模型训练完成后,需要将其部署为可访问的服务。高效的模型服务需要解决显存管理、请求调度、吞吐量优化等多个挑战。

推理与训练的区别

模型推理和训练在计算特性上有显著差异:

特性训练推理
计算模式前向+反向传播仅前向传播
批次大小固定或较大动态变化
延迟要求相对宽松严格(毫秒级)
显存使用参数+梯度+优化器状态仅参数+激活
精度要求高(影响收敛)可适当降低

推理服务的核心目标是:在满足延迟要求的前提下,最大化吞吐量

推理优化技术

模型量化

量化是将高精度浮点数转换为低精度表示,减少模型大小和计算量。

量化类型

类型说明精度损失
FP16半精度浮点极小
INT88位整数
INT44位整数中等
GPTQ/AWQ智能量化

示例:使用 bitsandbytes 进行量化

import torch
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
load_in_4bit=True,
torch_dtype=torch.float16,
device_map="auto"
)

KV Cache 优化

在自回归生成中,KV Cache 存储之前计算的 Key 和 Value,避免重复计算。

问题:KV Cache 随序列长度线性增长,可能占用大量显存

优化方案

  • PagedAttention(vLLM):将 KV Cache 分页管理,按需分配
  • MQA/GQA:多查询注意力,减少 KV 数量
  • Sliding Window:限制注意力窗口大小

连续批处理

传统批处理需要等待所有请求完成才能处理下一批,造成资源浪费。连续批处理动态调整批次:

传统批处理:
请求 A: [生成中...] [等待其他请求]
请求 B: [生成中...完成]
请求 C: [生成中...] [等待其他请求]

连续批处理:
请求 A: [生成中...]
请求 B: [生成中...完成]
请求 C: [生成中...]
↑ 新请求立即加入

投机解码

使用小模型预测多个 token,大模型验证:

小模型预测: [token1, token2, token3, token4]
大模型验证: [✓, ✓, ✓, ✗]
最终接受: [token1, token2, token3]

可以显著提升生成速度,特别是对于大模型。

vLLM

vLLM 是目前最流行的开源 LLM 推理引擎,以其高效的显存管理和高吞吐量著称。

核心技术

PagedAttention:受操作系统虚拟内存启发,将 KV Cache 分页管理:

传统方式:为每个请求预分配最大长度的连续内存
┌────────────────────────────────────────────────────┐
│ 请求1: [████████████████████████████████████████] │
│ 请求2: [████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░] │
│ 请求3: [████████████████████░░░░░░░░░░░░░░░░░░░░] │
└────────────────────────────────────────────────────┘
显存浪费严重

PagedAttention:按需分配内存块
┌────┬────┬────┬────┬────┬────┬────┬────┐
│ P1 │ P2 │ P3 │ P1 │ P4 │ P2 │ P5 │ P3 │
└────┴────┴────┴────┴────┴────┴────┴────┘
高效利用显存

安装和使用

pip install vllm

离线推理

from vllm import LLM, SamplingParams

llm = LLM(model="meta-llama/Llama-2-7b-hf")
sampling_params = SamplingParams(temperature=0.8, top_p=0.95, max_tokens=128)

prompts = [
"什么是机器学习?",
"请解释深度学习的概念。",
"自然语言处理有哪些应用?"
]

outputs = llm.generate(prompts, sampling_params)
for output in outputs:
print(output.outputs[0].text)

启动 API 服务

vllm serve meta-llama/Llama-2-7b-hf \
--host 0.0.0.0 \
--port 8000 \
--tensor-parallel-size 2

调用 API

import openai

client = openai.OpenAI(
base_url="http://localhost:8000/v1",
api_key="dummy"
)

response = client.chat.completions.create(
model="meta-llama/Llama-2-7b-hf",
messages=[{"role": "user", "content": "你好!"}],
max_tokens=100
)
print(response.choices[0].message.content)

关键参数

参数说明建议值
tensor-parallel-size张量并行数GPU 数量
gpu-memory-utilizationGPU 显存利用率0.9
max-model-len最大序列长度根据需求
block-size内存块大小16

TensorRT-LLM

TensorRT-LLM 是 NVIDIA 官方的高性能推理引擎,针对 NVIDIA GPU 进行了深度优化。

核心优势

  • 极致性能:充分利用 NVIDIA 硬件特性
  • 量化支持:INT8、INT4、FP8 等多种精度
  • 优化内核:高度优化的 CUDA 内核

使用流程

  1. 构建引擎:将模型转换为 TensorRT 引擎
python convert_checkpoint.py \
--model_dir /path/to/llama \
--output_dir /path/to/checkpoint \
--dtype float16

trtllm-build \
--checkpoint_dir /path/to/checkpoint \
--output_dir /path/to/engine \
--gemm_plugin float16
  1. 运行推理
from tensorrt_llm.runtime import ModelRunner

runner = ModelRunner.from_dir("/path/to/engine")
output = runner.generate("你好,请介绍一下自己。")
print(output)

与 Triton 集成

Triton Inference Server 提供生产级的服务能力:

# 启动 Triton Server
tritonserver --model-repository=/path/to/models

Ray Serve

Ray Serve 是 Ray 生态中的模型服务框架,支持复杂的推理流水线。

基本使用

from ray import serve
from starlette.requests import Request

@serve.deployment
class MyModelDeployment:
def __init__(self):
from transformers import AutoModelForCausalLM, AutoTokenizer
self.model = AutoModelForCausalLM.from_pretrained("gpt2")
self.tokenizer = AutoTokenizer.from_pretrained("gpt2")

async def __call__(self, request: Request):
data = await request.json()
inputs = self.tokenizer(data["text"], return_tensors="pt")
outputs = self.model.generate(**inputs, max_length=50)
return self.tokenizer.decode(outputs[0])

deployment = MyModelDeployment.bind()
serve.run(deployment)

多模型组合

@serve.deployment
class Preprocessor:
def __call__(self, text):
return text.lower().strip()

@serve.deployment
class Model:
def __init__(self, preprocessor):
self.preprocessor = preprocessor
self.model = load_model()

async def __call__(self, request):
text = await request.json()
processed = await self.preprocessor(text)
return self.model(processed)

deployment = Model.bind(Preprocessor.bind())
serve.run(deployment)

自动扩缩容

@serve.deployment(
autoscaling_config={
"min_replicas": 1,
"max_replicas": 10,
"target_num_ongoing_requests_per_replica": 5
}
)
class MyModel:
pass

Triton Inference Server

Triton 是 NVIDIA 开源的高性能推理服务器。

核心特性

  • 多框架支持:TensorFlow、PyTorch、ONNX、TensorRT
  • 动态批处理:自动合并请求提高吞吐
  • 模型编排:支持多模型流水线

配置示例

config.pbtxt

name: "llama"
backend: "tensorrtllm"
max_batch_size: 32
dynamic_batching {
max_queue_delay_microseconds: 100
}
instance_group [
{
count: 2
kind: KIND_GPU
}
]

性能指标与监控

关键指标

指标说明优化方向
TTFT首个 Token 延迟减少模型加载、优化调度
TPS每秒生成 Token 数提高计算效率
吞吐量每秒处理请求数批处理、并行
显存利用率GPU 显存使用率KV Cache 管理

监控工具

  • Prometheus + Grafana:通用监控方案
  • vLLM 内置指标/metrics 端点
  • NVIDIA DCGM:GPU 级别监控

实践建议

选择推理引擎

场景推荐方案
快速部署、高吞吐vLLM
NVIDIA GPU、极致性能TensorRT-LLM
复杂流水线Ray Serve
多模型、企业级Triton

优化策略

  1. 量化:根据精度要求选择 FP16、INT8 或 INT4
  2. 批处理:使用连续批处理提高吞吐
  3. 并行:多 GPU 张量并行
  4. 缓存:利用 KV Cache 避免重复计算

成本优化

  • Spot 实例:使用云厂商的竞价实例降低成本
  • 自动扩缩容:根据负载动态调整资源
  • 模型压缩:量化、蒸馏减小模型体积

小结

模型服务是 AI 应用落地的关键环节。选择合适的推理引擎、优化推理性能、构建可靠的服务架构,是提供高质量 AI 服务的基础。vLLM 以其易用性和高性能成为当前最流行的选择,而 TensorRT-LLM 则在 NVIDIA GPU 上提供极致性能。

参考资料