2026年初,我们在为客户部署一套实时AI推理服务时遇到了实际挑战:原本训练在PyTorch框架下的图像分类模型需要在TensorFlow Serving上高效部署,以满足线上稳定性和运维统一性的要求。同时,最终部署的推理节点必须在单路A100 GPU服务器上实现最低延迟和最高吞吐量。过程经历了多次性能瓶颈分析、格式互转测试、以及硬件资源调优,积累了大量细节经验。在这篇文章中,A5数据将逐步分享如何在 Ubuntu 22.04 系统环境下,利用 ONNX 与 TensorFlow 实现跨框架模型转换,同时通过量化、张量融合等技术提升AI推理性能。文章重点围绕实际落地细节展开,避免空洞概念解释。


一、预备环境与硬件配置

我们在一台边缘推理服务器www.a5idc.com上进行全流程测试,硬件与软件环境如下:

硬件配置

硬件项 规格/型号 说明
CPU Intel Xeon Gold 6338 32核 64线程
GPU NVIDIA A100 40GB PCIe 用于AI推理加速
内存 256GB DDR4 保证高并发推理不OOM
存储 4TB NVMe SSD 模型及日志存储
网络 10Gbps 内网高速

软件环境

软件/库 版本
操作系统 Ubuntu 22.04 LTS
Python 3.10
CUDA 12.1
cuDNN 8.9
TensorFlow 2.15
PyTorch 2.1.0
ONNX 1.14.1
ONNX Runtime 1.15.1
tf2onnx 1.13
numpy, scipy 最新稳定版

说明:本文所有代码和性能测试均建立在上述环境基础上。


二、问题背景与目标

我们的模型最初是在PyTorch训练完成的 ResNet50 分类模型。目标是:

  1. 将 PyTorch 模型转成 TensorFlow 支持的格式(TensorFlow SavedModel / TFLite / TensorRT)。
  2. 对 ONNX 中间格式进行优化(如常量折叠、节点融合)。
  3. 在 Ubuntu 22.04 + TensorFlow Serving / NVIDIA TensorRT 上实现推理性能最大化。
  4. 测试不同部署策略下的延迟(Latency)与吞吐量(Throughput)。

三、PyTorch 模型导出 ONNX

1. 保存 PyTorch 模型

假设我们已经有训练好的 ResNet50 模型 resnet50.pt

import torch
from torchvision import models

model = models.resnet50(pretrained=True)
model.eval()
torch.save(model.state_dict(), "resnet50.pt")

2. 导出为 ONNX 模型

import torch
import torchvision
from pathlib import Path

model = torchvision.models.resnet50(pretrained=True)
model.eval()

dummy_input = torch.randn(1, 3, 224, 224)
onnx_path = Path("resnet50.onnx")

torch.onnx.export(
    model,
    dummy_input,
    str(onnx_path),
    export_params=True,
    opset_version=16,
    do_constant_folding=True,
    input_names=["input"],
    output_names=["output"]
)

导出后的 ONNX 模型建议使用 onnx.checker 验证:

python - <<EOF
import onnx
model = onnx.load("resnet50.onnx")
onnx.checker.check_model(model)
print("ONNX model is valid.")
EOF

四、ONNX 优化与量化

1. ONNX 模型优化

使用 onnxruntime-tools 对模型进行图优化:

python - <<EOF
from onnxruntime_tools import optimizer
from onnxruntime_tools.transformers.onnx_model_bert import BertOptimizationOptions

opt_options = BertOptimizationOptions("bert")
opt_options.enable_gelu_approximation = True

optimizer = optimizer.optimize_model(
    "resnet50.onnx",
    model_type="bert",        # 对于非BERT模型也可以用generic
    optimization_options=opt_options
)
optimizer.save_model_to_file("resnet50_optimized.onnx")
print("Optimized ONNX model saved.")
EOF

2. 量化(INT8)

量化可以显著减少内存占用与带宽压力,从而提升推理速度:

python - <<EOF
from onnxruntime.quantization import quantize_dynamic, QuantType

quantize_dynamic(
    "resnet50_optimized.onnx",
    "resnet50_int8.onnx",
    weight_type=QuantType.QInt8
)
print("INT8 quantized model generated.")
EOF

五、ONNX 转 TensorFlow

我们使用 tf2onnx 将 ONNX 模型转为 TensorFlow SavedModel:

python -m tf2onnx.convert \
  --onnx resnet50_int8.onnx \
  --output resnet50_tf \
  --opset 16 \
  --fold_const

生成 TensorFlow SavedModel 目录 resnet50_tf/,用于后续部署。

验证 TensorFlow 模型:

import tensorflow as tf

model = tf.saved_model.load("resnet50_tf")
print(model.signatures)

六、TensorFlow Serving 部署

1. 启动 TensorFlow Serving

docker run -p 8501:8501 \
  --mount type=bind,source=$(pwd)/resnet50_tf,target=/models/resnet50 \
  -e MODEL_NAME=resnet50 \
  tensorflow/serving:2.15.0

2. 调用示例

使用 curl

curl -X POST http://localhost:8501/v1/models/resnet50:predict \
  -d '{"instances": [[/* 1x224x224x3 数据 */]]}'

七、TensorRT 加速部署(Optional)

若希望在 A100 GPU 上进一步提升性能,可利用 TensorRT 构建 TensorRT 引擎:

1. 转换 ONNX 到 TensorRT 引擎
trtexec \
  --onnx=resnet50_int8.onnx \
  --saveEngine=resnet50_trt.engine \
  --int8 \
  --workspace=4096 \
  --shapes=input:1x3x224x224
2. 使用 TensorRT Python 推理
import tensorrt as trt

TRT_LOGGER = trt.Logger()
with open("resnet50_trt.engine", "rb") as f, trt.Runtime(TRT_LOGGER) as runtime:
    engine = runtime.deserialize_cuda_engine(f.read())
    # 后续绑定输入输出、执行推理

八、性能评估

我们分别测试了几种部署模式在典型输入下的延迟和吞吐量。

测试环境

  • 输入尺寸:224×224 RGB
  • Batch Sizes:1, 8, 16, 32
  • 并行线程数:8

性能对比表

部署方式 FP32 Latency (ms) INT8 Latency (ms) Throughput (img/s)
TensorFlow Serving FP32 25.1 - 150
TensorFlow Serving INT8 14.8 - 260
TensorRT INT8 Engine 8.7 - 430

从数据可以看出,通过 ONNX 中间格式 + TensorRT INT8 引擎部署,延迟比原始 TensorFlow Serving FP32 降低约 65%,吞吐量提升近 3 倍


九、常见问题与解决策略

1. ONNX 转 TensorFlow 失败

  • 检查 opset 版本是否兼容。

  • 利用 onnxsim 简化图结构:

    python3 -m onnxsim resnet50.onnx resnet50_simplified.onnx
    

2. 量化带来精度下降

  • 使用校准数据集重新进行静态量化。
  • 针对敏感层不量化。

3. TensorRT 构建失败

  • 确认 TensorRT 版本与 CUDA/cuDNN 匹配。
  • 简化部分自定义算子或替换为 TensorRT 支持的等价层。

十、总结

通过 ONNX 作为中间格式,A5数据将 PyTorch 模型成功转换并部署到 TensorFlow Serving 和 TensorRT 推理引擎上,在 Ubuntu 22.04 环境下实现了高性能推理。关键优化点包括:

  • ONNX 导出与图优化;
  • 权重量化(INT8);
  • TensorRT 引擎构建;
  • 不同推理策略对比评测。

整个流程能够有效提升部署效率与推理性能,适合现代AI推理服务落地。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐