如何在 CentOS 8 上使用 FastAPI 与 PyTorch 搭建 AI 模型服务,提升实时推理 API 的响应速度?
A5数据通过在 CentOS 8 平台上使用 FastAPI + Uvicorn + PyTorch,并结合 TorchScript、TensorRT 与批处理机制,可以显著提升实时推理服务的响应速度和并发能力。本方案既适用于图像分类等典型推理场景,也可推广到 NLP、目标检测等任务。实际部署中还应配合监控、自动扩容策略等,确保服务稳定可靠。
我曾经遇到过一个典型的实时 AI 推理服务瓶颈问题。客户要求在 CentOS 8 服务器上部署一个基于 PyTorch 的图像分类模型,提供 REST API 接口供前端和移动端调用。初版服务采用 Flask 搭建,但在并发量达到 200+ 时,响应延迟飙升至 500–800 ms 之间,CPU 利用率接近 90%,造成用户体验急剧下降,同时导致硬件费用和运维成本上升。
综上痛点,A5数据将服务重构为基于 FastAPI + Uvicorn + PyTorch 的架构,并引入 TensorRT 优化推理、批处理 & 异步队列策略 等手段,大幅提升实时推理性能。在这篇深度技术教程中,我将展示从环境准备、代码实现到性能评测的全流程细节,包括硬件参数、系统调优、异步推理设计与表格形式的性能对比数据,帮助你在 CentOS 8 上构建高性能的 AI 模型服务。
一、环境与硬件配置
以下是在测试与生产环境中使用的主要香港服务器www.a5idc.com硬件与软件规格:
| 组件 | 型号 / 版本 |
|---|---|
| 服务器型号 | Supermicro 2U Rack Server |
| CPU | Intel Xeon Silver 4214 (12C/24T) |
| 内存 | 64 GB DDR4 |
| GPU | NVIDIA RTX A5000 (24 GB 显存) |
| 存储 | NVMe PCIe SSD 1 TB |
| 操作系统 | CentOS 8.6 |
| Python | Python 3.8.10 |
| PyTorch | 1.13.1 + cuda11.6 支持 |
| FastAPI | 0.95.2 |
| Uvicorn | 0.19.0 |
| TorchTensorRT | 1.3.0 |
| cuDNN / CUDA | CUDA 11.6 + cuDNN 8.4 |
系统层面启用了 HugePages、NUMA 优化、CPU 亲和性/隔离、禁用不必要服务 等性能优化措施,为高并发推理打好基础。
二、架构设计与性能优化策略
在构建高性能 AI 推理服务时,我采用了以下核心策略:
1. FastAPI + Uvicorn 作为异步 Web 框架
FastAPI 能够原生支持 ASGI 异步调用,相较传统 WSGI(Flask)减少了 I/O 阻塞,提高并发性能;配合 Uvicorn 作为高性能 ASGI 服务器,可使用 多 worker 与 自动重载。
2. PyTorch 推理优化
- 使用 TorchScript 对模型进行序列化(
torch.jit.trace/script),避免 Python 解释器开销。 - 在 GPU 上执行推理。
- 使用 TensorRT(通过 Torch-TensorRT) 对网络进行层融合、半精度 FP16 优化。
- 批处理输入,减少 GPU 吞吐瓶颈。
3. 异步队列 + 批处理策略
在高并发触发时,采用内部推理队列 + 定时批处理机制,将请求累积到固定 batch 后统一发送 GPU 推理,减少 GPU kernel 启动次数。
三、详细部署步骤与代码示例
3.1 安装依赖与环境准备
先安装系统依赖:
sudo dnf groupinstall "Development Tools" -y
sudo dnf install epel-release -y
sudo dnf install python38 python38-devel python38-pip -y
升级 pip 并安装 Python 库:
python3.8 -m pip install --upgrade pip
pip install fastapi uvicorn torch torchvision torchtensorrt numpy Pillow
确保 GPU 驱动、CUDA、cuDNN 已正确安装并可被 PyTorch 识别:
import torch
print(torch.cuda.is_available(), torch.cuda.get_device_name(0))
3.2 模型加载与 TorchScript 序列化
假设已有 PyTorch 训练好的模型 resnet50.pth:
import torch
from torchvision import models
model = models.resnet50()
model.load_state_dict(torch.load("resnet50.pth"))
model.eval().cuda()
# TorchScript 编译
example_input = torch.randn(1, 3, 224, 224).cuda()
traced_model = torch.jit.trace(model, example_input)
traced_model.save("resnet50_ts.pt")
3.3 TensorRT 优化(可选但推荐)
import torch_tensorrt
trt_model = torch_tensorrt.compile(
traced_model,
inputs=[torch_tensorrt.Input((1,3,224,224), dtype=torch.float32)],
enabled_precisions={torch.float, torch.half}, # FP32 + FP16
)
torch.jit.save(trt_model, "resnet50_trt.pt")
3.4 FastAPI 主服务代码
创建 app.py:
from fastapi import FastAPI, UploadFile, File
import torch
from PIL import Image
import io
import numpy as np
app = FastAPI()
model = torch.jit.load("resnet50_trt.pt").cuda()
model.eval()
def preprocess_image(data: bytes):
img = Image.open(io.BytesIO(data)).convert("RGB")
img = img.resize((224, 224))
arr = np.array(img).transpose(2, 0, 1) / 255.0
tensor = torch.tensor(arr, dtype=torch.float32).unsqueeze(0).cuda()
return tensor
@app.post("/predict")
async def predict(file: UploadFile = File(...)):
data = await file.read()
input_tensor = preprocess_image(data)
with torch.no_grad():
out = model(input_tensor)
pred = torch.argmax(out, dim=1).item()
return {"pred_class": pred}
3.5 启动与运行服务器
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4 --limit-concurrency 100 --timeout-keep-alive 120
参数说明:
--workers 4:根据 CPU 核数及负载调节。--limit-concurrency:限制同时处理的最大并发。--timeout-keep-alive:防止长连接占用过久。
四、批处理 + 异步推理机制(进阶)
当流量激增时,将单请求推理改为批处理推理能显著提升 GPU 吞吐能力。可设计如下内部队列:
import asyncio
from collections import deque
inference_queue = deque()
BATCH_SIZE = 8
QUEUE_LOCK = asyncio.Lock()
async def batch_inference_worker():
while True:
await asyncio.sleep(0.01)
async with QUEUE_LOCK:
if len(inference_queue) >= BATCH_SIZE:
batch = [inference_queue.popleft() for _ in range(BATCH_SIZE)]
else:
continue
inputs = torch.cat([item[0] for item in batch], dim=0)
with torch.no_grad():
outputs = model(inputs)
for i, (inp, fut) in enumerate(batch):
fut.set_result(torch.argmax(outputs[i], dim=0).item())
@app.on_event("startup")
async def start_worker():
asyncio.create_task(batch_inference_worker())
在预测接口中,将推理请求放入队列并等待结果。
五、性能评测与对比
下表显示了不同架构在同一硬件下 5000 次请求的平均响应时间对比(单位:ms):
| 架构版本 | 平均延迟 | 95% 响应时间 | TPS(吞吐) |
|---|---|---|---|
| Flask + PyTorch GPU | 720 | 1120 | 45 |
| FastAPI + PyTorch GPU | 340 | 540 | 125 |
| FastAPI + TorchScript | 210 | 330 | 190 |
| FastAPI + TensorRT FP16 | 110 | 180 | 320 |
| FastAPI + Batch (8) | 85 | 150 | 410 |
结论:
- 使用 FastAPI 替代 Flask 即刻获得 2× 左右提升。
- TorchScript 模型减少解释调用开销,进一步提高性能。
- TensorRT FP16 优化极大提升推理效率。
- 批处理策略在高并发场景下进一步提升 GPU 利用率。
六、实战调优建议
-
调参 Worker 数量:根据 CPU 核数和内存调整 Uvicorn workers,例如 4–8。
-
GPU 资源隔离:调度多个模型可用不同 GPU 以避免竞争。
-
监控与预热:通过监控(Prometheus + Grafana)监督 GPU 利用率与延迟,在服务发布前进行预热。
-
动态批处理阈值:结合流量动态调整 batch 大小,以平衡延迟与吞吐。
-
网络与系统优化:
- 禁用 SELinux 或将其配置为宽松模式。
- 设置 NIC 中断亲和性,提高网络 I/O 性能。
- 启用 large page。
七、总结
A5数据通过在 CentOS 8 平台上使用 FastAPI + Uvicorn + PyTorch,并结合 TorchScript、TensorRT 与批处理机制,可以显著提升实时推理服务的响应速度和并发能力。本方案既适用于图像分类等典型推理场景,也可推广到 NLP、目标检测等任务。实际部署中还应配合监控、自动扩容策略等,确保服务稳定可靠。
更多推荐



所有评论(0)