2. 推理引擎概览

各位同学,今天我们来聊聊推理引擎。说实话,我刚入行那会儿,市面上能用的推理工具屈指可数。现在倒好,百花齐放,反而让人挑花了眼。你想想看,一个模型训练出来,总不能永远待在 PyTorch 或者 TensorFlow 的温室里吧?它得部署到实际场景中去——手机、服务器、边缘设备,甚至汽车里。这时候,推理引擎就派上用场了。

我个人习惯把推理引擎比作「翻译官」。它把训练好的模型,翻译成目标硬件能听懂的语言。翻译得好不好,直接决定了你的模型跑得快不快、省不省电、稳不稳定。今天咱们就挑三个最主流的选手来聊聊:TensorRT、ONNX Runtime 和 OpenVINO。

为什么需要推理引擎?

先问一个问题:为什么不能直接用训练框架做推理?

嗯,这里有个关键点。训练框架追求的是灵活性——你要能随时改网络结构、调参数、算梯度。但推理不一样,推理追求的是极致的效率。你想想看,一个模型在服务器上可能要同时服务上千个请求,每慢一毫秒,用户体验就差一截。

我在项目中遇到过这样的情况:用 PyTorch 直接做推理,一张图片要 50 毫秒。换成 TensorRT 优化后,直接降到 8 毫秒。差距就是这么明显。

推理引擎的核心工作,说白了就是三件事:

  • 图优化:把计算图做等价变换,比如算子融合、常量折叠、死代码消除
  • 量化:把 FP32 的权重和激活值,压缩成 INT8 甚至 INT4
  • 内存优化:减少显存碎片,复用缓冲区

这三板斧下去,性能翻个几倍是很常见的事。

TensorRT:NVIDIA 的王牌

先说说 TensorRT。如果你用的是 NVIDIA 的 GPU,那 TensorRT 几乎是绕不开的选择。

TensorRT 的定位非常明确——专为 NVIDIA GPU 打造的高性能推理引擎。它不是一个通用的框架,它只认 NVIDIA 的硬件。好处是什么?极致的优化。坏处是什么?你换不了别的硬件。

我记得有一次,客户想把一个部署在 T4 上的模型迁移到 A100 上。理论上都是 NVIDIA 的卡,应该没问题吧?结果发现 TensorRT 对 A100 的稀疏计算有专门的优化路径,需要重新做一次 profiling 和 tuning。嗯,这里要注意,TensorRT 的优化是跟具体 GPU 架构绑定的。

TensorRT 的核心能力包括:

  • 层融合:把 Conv + BN + ReLU 这种常见组合,合并成一个 kernel 执行
  • 精度校准:INT8 量化时,通过校准数据集找到最佳的截断阈值
  • 动态形状:支持输入尺寸不固定的场景,比如 NLP 里的变长序列

下面是一个简单的 TensorRT 推理流程示例:

// 伪代码:TensorRT 推理流程
// 1. 创建 builder
IBuilder* builder = createInferBuilder(gLogger);

// 2. 创建 network
INetworkDefinition* network = builder->createNetwork();

// 3. 解析 ONNX 模型
parser->parse(modelFile, network);

// 4. 构建 engine
IBuilderConfig* config = builder->createBuilderConfig();
config->setMemoryPoolLimit(MemoryPoolType::kWORKSPACE, 1 << 20);
IHostMemory* serializedModel = builder->buildSerializedNetwork(*network, *config);

// 5. 反序列化并执行推理
IRuntime* runtime = createInferRuntime(gLogger);
ICudaEngine* engine = runtime->deserializeCudaEngine(serializedModel);

这段代码看着简单,但实际调优的时候坑不少。我曾经因为 workspace 设得太小,导致某些算子退回到 CPU 执行,性能直接腰斩。所以我的建议是:先用默认配置跑一遍,再逐步调优。

ONNX Runtime:跨平台的瑞士军刀

接下来聊聊 ONNX Runtime。这个引擎的定位跟 TensorRT 完全不同。它不挑硬件,CPU、GPU、NPU 都能跑。它的核心优势是跨平台和开放性。

ONNX Runtime 的背后是 ONNX 这个开放标准。你想想看,如果你用 PyTorch 训练,导出 ONNX 模型,然后用 ONNX Runtime 部署到 Windows、Linux、甚至手机上,是不是很爽?

我在项目中用过 ONNX Runtime 做 CPU 上的推理。说实话,在 CPU 上它的表现相当不错。它用了很多手写的 kernel,针对不同 CPU 指令集做了优化。比如 AVX2、AVX512,它都能充分利用。

ONNX Runtime 的架构设计很有意思:

  • Execution Provider(EP):这是它的核心抽象。每个 EP 负责在特定硬件上执行算子。比如 CUDA EP 跑在 GPU 上,OpenVINO EP 跑在 Intel 的硬件上
  • Graph Optimizer:做图级别的优化,比如算子融合、常量折叠
  • Session:管理推理的上下文,包括模型加载、内存分配

下面是一个 ONNX Runtime 的 Python 调用示例:

import onnxruntime as ort

# 创建 session,指定使用 CPU
sess = ort.InferenceSession('model.onnx',
                            providers=['CPUExecutionProvider'])

# 获取输入输出信息
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})

这段代码看着简单,但有个细节要注意:providers 参数的顺序决定了优先级。如果你同时指定了 CUDA 和 CPU,ONNX Runtime 会优先尝试 CUDA。如果某个算子 CUDA 不支持,才会 fallback 到 CPU。

小技巧:在 ONNX Runtime 中,你可以通过 ort.get_available_providers() 查看当前环境支持哪些 EP。我建议在部署脚本里加上这个检查,避免因为缺少某个 provider 导致运行时崩溃。

OpenVINO:Intel 生态的利器

最后说说 OpenVINO。如果你用的是 Intel 的 CPU、集成显卡或者 Movidius 神经计算棒,那 OpenVINO 是你的不二之选。

OpenVINO 的全称是 Open Visual Inference and Neural Network Optimization。名字很长,但核心就一句话:让 Intel 硬件上的推理跑得更快。

它的架构分两层:

  • Model Optimizer:负责把训练好的模型(比如 TensorFlow、PyTorch、ONNX)转换成 OpenVINO 的中间表示(IR)
  • Inference Engine:负责加载 IR 并在目标硬件上执行推理

我曾经在一个项目中,需要把模型部署到一台只有 Intel CPU 的工控机上。没有 GPU,没有加速卡。当时试了 ONNX Runtime,性能一般。换成 OpenVINO 后,推理速度提升了将近 3 倍。为什么?因为 OpenVINO 针对 Intel CPU 的 AVX-512 指令集做了深度优化,还用了很多手写的汇编级 kernel。

OpenVINO 的推理流程大概是这样的:

# 伪代码:OpenVINO 推理流程
# 1. 加载 IR 模型
core = Core()
model = core.read_model('model.xml', 'model.bin')

# 2. 编译模型到指定设备
compiled_model = core.compile_model(model, 'CPU')

# 3. 创建推理请求
infer_request = compiled_model.create_infer_request()

# 4. 设置输入并执行
input_tensor = infer_request.get_input_tensor()
input_tensor.data[:] = input_data
infer_request.infer()

# 5. 获取输出
output_tensor = infer_request.get_output_tensor()
result = output_tensor.data[:]

这里有个坑:OpenVINO 的 IR 模型是分两个文件的——.xml 描述网络结构,.bin 存放权重。两个文件缺一不可。我曾经因为只拷贝了 .xml 文件到部署环境,结果推理时直接报错。嗯,这种低级错误犯过一次就不会再犯了。

三者的对比与选型建议

好了,三个引擎都聊完了。咱们做个对比:

特性 TensorRT ONNX Runtime OpenVINO
目标硬件 NVIDIA GPU CPU/GPU/NPU 等 Intel CPU/GPU/VPU
优化深度 极深(算子级 + 图级) 中等(图级为主) 深(针对 Intel 架构)
量化支持 INT8/FP16/INT4 INT8/FP16 INT8/FP16
动态形状 支持(需配置) 原生支持 有限支持
跨平台 仅 Linux/Windows 全平台 Linux/Windows/macOS

选型的时候,我的建议很简单:

  • 如果你用的是 NVIDIA GPU,优先选 TensorRT。别犹豫,性能差距摆在那里
  • 如果你需要跨平台部署,或者硬件不固定,选 ONNX Runtime。它的兼容性是最好的
  • 如果你用的是 Intel 的硬件,尤其是 CPU 或者集成显卡,试试 OpenVINO。它能把 Intel 硬件的潜力榨干
注意:不要试图用一个引擎解决所有问题。我见过有人非要在 AMD 的 GPU 上跑 TensorRT,结果折腾了两周,最后还是换成了 ONNX Runtime。选型要务实,别跟硬件较劲。

一张图看懂推理引擎的定位

下面我用一张 SVG 图来总结这三个引擎的定位和关系:

推理引擎定位与架构 训练框架:PyTorch / TensorFlow / PaddlePaddle 中间表示:ONNX / OpenVINO IR / TensorRT Plan TensorRT NVIDIA GPU 专属优化 ONNX Runtime 跨平台通用推理 OpenVINO Intel 硬件深度优化 硬件:NVIDIA GPU / Intel CPU & GPU / AMD / ARM / NPU

这张图很直观地展示了从训练框架到硬件之间的完整链路。你想想看,中间那一层就是推理引擎的战场。不同的引擎,覆盖不同的硬件,优化深度也各不相同。

好了,这一章的内容就到这里。记住一句话:没有最好的引擎,只有最合适的引擎。选型的时候,先搞清楚你的硬件是什么,再考虑你的部署场景,最后才是性能指标。顺序别搞反了。