模型服务与推理
模型训练完成后,需要将其部署为可访问的服务。高效的模型服务需要解决显存管理、请求调度、吞吐量优化等多个挑战。
推理与训练的区别
模型推理和训练在计算特性上有显著差异:
| 特性 | 训练 | 推理 |
|---|---|---|
| 计算模式 | 前向+反向传播 | 仅前向传播 |
| 批次大小 | 固定或较大 | 动态变化 |
| 延迟要求 | 相对宽松 | 严格(毫秒级) |
| 显存使用 | 参数+梯度+优化器状态 | 仅参数+激活 |
| 精度要求 | 高(影响收敛) | 可适当降低 |
推理服务的核心目标是:在满足延迟要求的前提下,最大化吞吐量。
推理优化技术
模型量化
量化是将高精度浮点数转换为低精度表示,减少模型大小和计算量。
量化类型:
| 类型 | 说明 | 精度损失 |
|---|---|---|
| FP16 | 半精度浮点 | 极小 |
| INT8 | 8位整数 | 小 |
| INT4 | 4位整数 | 中等 |
| 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-utilization | GPU 显存利用率 | 0.9 |
max-model-len | 最大序列长度 | 根据需求 |
block-size | 内存块大小 | 16 |
TensorRT-LLM
TensorRT-LLM 是 NVIDIA 官方的高性能推理引擎,针对 NVIDIA GPU 进行了深度优化。
核心优势
- 极致性能:充分利用 NVIDIA 硬件特性
- 量化支持:INT8、INT4、FP8 等多种精度
- 优化内核:高度优化的 CUDA 内核
使用流程
- 构建引擎:将模型转换为 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
- 运行推理:
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 |
优化策略
- 量化:根据精度要求选择 FP16、INT8 或 INT4
- 批处理:使用连续批处理提高吞吐
- 并行:多 GPU 张量并行
- 缓存:利用 KV Cache 避免重复计算
成本优化
- Spot 实例:使用云厂商的竞价实例降低成本
- 自动扩缩容:根据负载动态调整资源
- 模型压缩:量化、蒸馏减小模型体积
小结
模型服务是 AI 应用落地的关键环节。选择合适的推理引擎、优化推理性能、构建可靠的服务架构,是提供高质量 AI 服务的基础。vLLM 以其易用性和高性能成为当前最流行的选择,而 TensorRT-LLM 则在 NVIDIA GPU 上提供极致性能。