Skip to content

推理服务部署

推理服务架构

客户端请求

API Gateway(限流/鉴权/路由)

推理服务集群(多副本)
    ├── 推理实例1(GPU)
    ├── 推理实例2(GPU)
    └── 推理实例3(GPU)

模型仓库(Model Registry)

TensorRT 模型优化

TensorRT 是 NVIDIA 的推理优化引擎,可将训练好的模型转换为高效推理格式:

python
import tensorrt as trt
import torch
import numpy as np

# 步骤1:将 PyTorch 模型导出为 ONNX
model = load_trained_model()
model.eval()

dummy_input = torch.randn(1, 3, 224, 224).cuda()
torch.onnx.export(
    model,
    dummy_input,
    "model.onnx",
    opset_version=17,
    input_names=["input"],
    output_names=["output"],
    dynamic_axes={"input": {0: "batch_size"}}  # 动态 batch
)

# 步骤2:使用 trtexec 转换为 TensorRT 引擎
# trtexec --onnx=model.onnx \
#         --saveEngine=model.trt \
#         --fp16 \                    # 开启 FP16 精度
#         --minShapes=input:1x3x224x224 \
#         --optShapes=input:8x3x224x224 \
#         --maxShapes=input:32x3x224x224

# 步骤3:加载 TensorRT 引擎推理
import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit

TRT_LOGGER = trt.Logger(trt.Logger.WARNING)

with open("model.trt", "rb") as f:
    engine_data = f.read()

runtime = trt.Runtime(TRT_LOGGER)
engine = runtime.deserialize_cuda_engine(engine_data)
context = engine.create_execution_context()

# 推理
input_data = np.random.randn(8, 3, 224, 224).astype(np.float16)
# ... 执行推理

vLLM 大语言模型推理

vLLM 是目前最流行的 LLM 推理框架,H3C AI Platform 原生集成:

python
from vllm import LLM, SamplingParams

# 加载模型(自动使用所有可用 GPU)
llm = LLM(
    model="/models/Qwen2-72B-Instruct",
    tensor_parallel_size=4,    # 4 张 GPU 张量并行
    gpu_memory_utilization=0.9,
    max_model_len=8192,
    dtype="bfloat16"
)

# 批量推理
prompts = [
    "请介绍一下新华三公司的主要产品",
    "什么是云计算的 IaaS 层?",
    "解释一下 Kubernetes 的核心概念"
]

sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=512
)

outputs = llm.generate(prompts, sampling_params)

for output in outputs:
    print(f"问题: {output.prompt}")
    print(f"回答: {output.outputs[0].text}")
    print("---")

vLLM OpenAI 兼容 API 服务

bash
# 启动 vLLM 服务(兼容 OpenAI API)
python -m vllm.entrypoints.openai.api_server \
  --model /models/Qwen2-72B-Instruct \
  --tensor-parallel-size 4 \
  --host 0.0.0.0 \
  --port 8000 \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.9
python
# 客户端调用(兼容 OpenAI SDK)
from openai import OpenAI

client = OpenAI(
    base_url="http://inference.ai-platform.example.com:8000/v1",
    api_key="not-needed"  # vLLM 本地部署无需 key
)

response = client.chat.completions.create(
    model="Qwen2-72B-Instruct",
    messages=[
        {"role": "system", "content": "你是新华三的技术专家助手"},
        {"role": "user", "content": "请介绍 H3C CloudOS 的核心架构"}
    ],
    temperature=0.7,
    max_tokens=1024,
    stream=True  # 流式输出
)

for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Triton 推理服务器

NVIDIA Triton 是企业级推理服务框架,支持多框架模型:

模型仓库结构:
model_repository/
├── bert_classifier/
│   ├── config.pbtxt
│   └── 1/
│       └── model.onnx
├── resnet50/
│   ├── config.pbtxt
│   └── 1/
│       └── model.plan  (TensorRT)
└── ensemble_pipeline/
    ├── config.pbtxt
    └── 1/
        └── (空,ensemble 无需模型文件)
protobuf
# config.pbtxt 示例(BERT 分类器)
name: "bert_classifier"
platform: "onnxruntime_onnx"
max_batch_size: 32

input [
  {
    name: "input_ids"
    data_type: TYPE_INT64
    dims: [128]  # 序列长度
  },
  {
    name: "attention_mask"
    data_type: TYPE_INT64
    dims: [128]
  }
]

output [
  {
    name: "logits"
    data_type: TYPE_FP32
    dims: [2]  # 二分类
  }
]

instance_group [
  {
    count: 2      # 2 个推理实例
    kind: KIND_GPU
    gpus: [0, 1]  # 使用 GPU 0 和 1
  }
]

dynamic_batching {
  preferred_batch_size: [8, 16, 32]
  max_queue_delay_microseconds: 5000  # 最大等待 5ms 凑批
}
bash
# 启动 Triton 服务器
docker run --gpus all --rm \
  -p 8000:8000 -p 8001:8001 -p 8002:8002 \
  -v /path/to/model_repository:/models \
  nvcr.io/nvidia/tritonserver:23.10-py3 \
  tritonserver --model-repository=/models

# 检查模型状态
curl http://localhost:8000/v2/models/bert_classifier/ready

# 发送推理请求
curl -X POST http://localhost:8000/v2/models/bert_classifier/infer \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": [
      {"name": "input_ids", "shape": [1, 128], "datatype": "INT64", "data": [...]},
      {"name": "attention_mask", "shape": [1, 128], "datatype": "INT64", "data": [...]}
    ]
  }'

推理性能优化

量化(Quantization)

python
# INT8 量化(减少显存,提升吞吐)
from transformers import AutoModelForSequenceClassification
import torch

model = AutoModelForSequenceClassification.from_pretrained("bert-base-chinese")

# 动态量化(简单,精度损失小)
quantized_model = torch.quantization.quantize_dynamic(
    model,
    {torch.nn.Linear},  # 量化线性层
    dtype=torch.qint8
)

# 性能对比:
# FP32:基准
# FP16:速度 ~2x,显存 ~0.5x
# INT8:速度 ~4x,显存 ~0.25x,精度损失 < 1%

KV Cache 优化(LLM)

python
# vLLM 的 PagedAttention 自动管理 KV Cache
# 无需手动配置,但需要了解原理

# KV Cache 大小估算:
# 每个 token 的 KV Cache = 2 × num_layers × num_heads × head_dim × dtype_bytes
# 以 Llama-2-70B 为例:
#   2 × 80 × 64 × 128 × 2(FP16)= 2.6MB/token
#   8192 tokens × 2.6MB = 21GB(单请求)
# 因此 70B 模型推理需要大量显存用于 KV Cache

褚成志的云与计算笔记