2. 推理引擎入门
推理引擎这东西,说白了就是帮你把训练好的模型跑起来的工具。我刚开始接触NPU推理那会儿,也踩过不少坑——选错了引擎,性能直接腰斩。今天咱们就聊聊市面上最主流的三个引擎:TensorRT、ONNX Runtime、OpenVINO,以及怎么根据场景选。
2.1 三大主流推理引擎概览
先看一张图,帮你快速建立整体认知。我个人习惯用这张图来给团队新人做入门培训。
2.2 TensorRT:NVIDIA 生态的王牌
TensorRT 是 NVIDIA 推出的推理优化引擎。如果你用的是 NVIDIA GPU,那它基本是首选。我最早接触 TensorRT 是在一个自动驾驶项目里,当时模型在 PyTorch 上跑推理要 30ms,换成 TensorRT 后直接降到 8ms——嗯,这个差距你想想看。
核心特性
- 层融合:把多个连续的小算子合并成一个,减少 kernel 启动开销
- 精度校准:支持 FP16、INT8 甚至 INT4 量化,精度损失可控
- 动态形状:可以处理变长输入,不用每次都重新构建引擎
- 插件机制:支持自定义算子,遇到不支持的 op 可以自己写
关键点:TensorRT 的 INT8 量化需要校准数据集。我曾经因为校准集选得不好,导致模型精度掉了 5 个点,后来换了覆盖更全的数据才解决。
典型用法
import tensorrt as trt
# 构建引擎
logger = trt.Logger(trt.Logger.WARNING)
builder = trt.Builder(logger)
network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
# 解析 ONNX 模型
parser = trt.OnnxParser(network, logger)
with open("model.onnx", "rb") as f:
parser.parse(f.read())
# 配置优化
config = builder.create_builder_config()
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 30) # 1GB
config.set_flag(trt.BuilderFlag.FP16) # 开启 FP16
# 序列化引擎
serialized_engine = builder.build_serialized_network(network, config)
with open("model.trt", "wb") as f:
f.write(serialized_engine)
个人经验:构建 TensorRT 引擎时,workspace 大小别设太小。我一般设 1GB 起步,否则大模型容易构建失败。
2.3 ONNX Runtime:跨平台的瑞士军刀
ONNX Runtime 是微软开源的推理引擎。它最大的优势是跨平台——你训练好的模型转成 ONNX 格式,就能在 Windows、Linux、macOS 甚至手机上跑。我个人习惯用 ONNX Runtime 做原型验证,因为它部署起来最快。
核心特性
- 多后端执行:CPU 用 MLAS,GPU 用 CUDA,NPU 用 DNNL
- 模型优化:自动做常量折叠、算子融合
- 语言支持:Python、C++、C#、Java 都有 API
- 量化工具:内置 INT8 和 UINT8 量化
避坑指南:我曾经在 ONNX Runtime 上踩过一个坑——某些自定义算子 ONNX 不支持,需要自己写 Custom Op。后来我改用 TensorRT 的插件机制才解决。所以如果你的模型有很多自定义层,先检查 ONNX 算子支持列表。
典型用法
import onnxruntime as ort
# 创建推理会话
sess = ort.InferenceSession("model.onnx", providers=['CUDAExecutionProvider'])
# 获取输入输出信息
input_name = sess.get_inputs()[0].name
output_name = sess.get_outputs()[0].name
# 执行推理
import numpy as np
input_data = np.random.randn(1, 3, 224, 224).astype(np.float32)
result = sess.run([output_name], {input_name: input_data})
小技巧:ONNX Runtime 支持多个 provider 同时配置。你可以设 ['CUDAExecutionProvider', 'CPUExecutionProvider'],这样 GPU 不行时自动 fallback 到 CPU。
2.4 OpenVINO:Intel 平台的优化利器
OpenVINO 是 Intel 推出的推理框架。如果你用的是 Intel CPU、集成显卡或者 Movidius VPU,那 OpenVINO 是首选。我记得有一次在 Intel Xeon 上跑一个视觉模型,用 OpenVINO 优化后延迟从 50ms 降到了 12ms——这优化幅度,说实话挺震撼的。
核心特性
- 模型优化器:把各种框架的模型转成 IR(Intermediate Representation)格式
- 异构执行:可以把不同算子分配到不同硬件上跑
- 低精度支持:INT8 量化,精度损失很小
- 边缘优化:针对边缘设备做了大量优化
关键点:OpenVINO 的模型优化器(MO)支持从 TensorFlow、PyTorch、ONNX 等格式直接转换。但要注意——某些算子可能不支持,需要手动替换。
典型用法
from openvino.runtime import Core
# 加载模型
core = Core()
model = core.read_model("model.xml")
# 编译模型
compiled_model = core.compile_model(model, "CPU")
# 创建推理请求
infer_request = compiled_model.create_infer_request()
# 执行推理
import numpy as np
input_data = np.random.randn(1, 3, 224, 224).astype(np.float32)
infer_request.infer({0: input_data})
result = infer_request.get_output_tensor(0).data
个人经验:OpenVINO 的 INT8 量化需要校准数据集。我建议用 200-500 张代表性图片做校准,太少精度会掉,太多浪费时间。
2.5 引擎选型策略:怎么选?
选推理引擎,说白了就是看你的硬件平台和业务需求。我总结了一个选型表格,你直接对照着看就行。
| 场景 | 推荐引擎 | 理由 |
|---|---|---|
| NVIDIA GPU 服务器 | TensorRT | 性能最优,支持 FP16/INT8 量化 |
| Intel CPU/GPU 边缘设备 | OpenVINO | 针对 Intel 硬件深度优化 |
| 跨平台部署(Win/Linux/Mac) | ONNX Runtime | 多后端支持,部署灵活 |
| 移动端/嵌入式 | ONNX Runtime + NNAPI | 支持 Android NNAPI 加速 |
| 快速原型验证 | ONNX Runtime | 部署最快,API 简洁 |
| 生产环境高性能推理 | TensorRT | 延迟最低,吞吐最高 |
选型决策流程
- 看硬件:先确定你的目标硬件平台。NVIDIA GPU 选 TensorRT,Intel 平台选 OpenVINO,其他情况选 ONNX Runtime。
- 看模型:检查模型里有没有自定义算子。如果有,优先考虑 TensorRT(插件机制最成熟)或 ONNX Runtime(Custom Op 支持)。
- 看性能需求:如果延迟要求苛刻(比如 <10ms),TensorRT 是首选。如果只是跑通就行,ONNX Runtime 最省事。
- 看部署环境:如果要在多个平台部署,ONNX Runtime 最合适。如果只针对一个平台,用对应的专用引擎。
避坑指南:我曾经在一个项目里,团队选了 ONNX Runtime 部署到 NVIDIA GPU 上。结果发现性能比 TensorRT 差了 30%。后来我们花了三天时间迁移到 TensorRT,性能才达标。所以——如果硬件确定是 NVIDIA GPU,别犹豫,直接上 TensorRT。
2.6 我的个人建议
做了这么多年推理优化,我总结了几条经验:
- 不要迷信某个引擎:每个引擎都有它的适用场景。TensorRT 在 GPU 上很强,但在 CPU 上就不如 OpenVINO。
- 先跑通再优化:我习惯先用 ONNX Runtime 跑通整个流程,确认模型没问题后,再切换到专用引擎做性能优化。
- 量化要谨慎:INT8 量化能带来 2-4 倍性能提升,但精度可能会掉。我建议先做 FP16,精度没问题再尝试 INT8。
- 多测试不同 batch size:有些引擎在小 batch 下表现好,有些在大 batch 下更优。你想想看,如果业务需要高吞吐,batch size 设大点可能更划算。
一句话总结:选推理引擎,先看硬件,再看模型,最后看性能需求。没有最好的引擎,只有最适合你场景的引擎。