ONNX Runtime 基础与安装

咱们开始聊 ONNX Runtime。说实话,这东西我第一次见就觉得——嗯,这名字挺直白的。Runtime,运行时,专门用来跑 ONNX 模型的。我最早接触它是在一个图像分类项目里,模型用 PyTorch 训练完,导出成 ONNX,然后丢到 ONNX Runtime 里一跑——速度直接翻倍。

你想想看,ONNX 只是个中间格式,谁来执行它?目前主流的选择就是 ONNX Runtime。微软开源的推理引擎,支持 Windows、Linux、Mac,还能无缝切到 CPU、GPU、甚至边缘设备。我个人的习惯是:只要模型结构固定,上线前我一定先试 ONNX Runtime + TensorRT 后端。

ONNX Runtime 到底是什么?

说白了一个跨平台推理加速库。它把 ONNX 模型解析成计算图,然后针对不同硬件做图优化、算子融合、内存复用。你不需要改模型代码,只要换一行代码就能切后端。核心优势有三点:

  • 高性能:内置图优化 pass,自动选择最优 kernel。
  • 跨平台:从服务器到手机嵌入式,全都能跑。
  • 多后端:CPU、CUDA、TensorRT、OpenVINO、DirectML、CoreML,想用哪个用哪个。

我遇到过不少团队,模型跑在 GPU 上嫌贵,想改 CPU 又怕慢。这时候 ONNX Runtime 的 OpenVINO 后端就很香——Intel CPU 上能达到接近 GPU 的性能。

安装方式:pip vs 源码编译

安装 ONNX Runtime 有两种主流方式:pip 安装和源码编译。怎么选?我的经验是:90% 的场景用 pip 就够了,除非你需要定制算子或编译非官方后端。

pip 安装(推荐新手)

一句话搞定:

pip install onnxruntime

这是 CPU 版。想要 GPU 加速?那就装 GPU 版:

pip install onnxruntime-gpu

但注意啊,GPU 版默认依赖 CUDA 和 cuDNN,版本要对齐。我有一回手快装了最新版,结果 CUDA 11.8 没装,报错找不到库——浪费时间。

如果你用 Intel CPU,想用 OpenVINO 后端,可以用:

pip install onnxruntime-openvino

还有针对 ARM 的:

pip install onnxruntime-arm64

不同变体对比:

pip 包名 后端 适用场景
onnxruntime CPU (通用) 开发测试、CPU 推理
onnxruntime-gpu CUDA + TensorRT NVIDIA GPU 推理
onnxruntime-openvino OpenVINO Intel CPU/GPU/VPU
onnxruntime-arm64 ARM CPU 树莓派、Jetson

我的提示:装 GPU 版之前,先查你的 CUDA 版本。运行 nvidia-smi 看左上角。然后去 ONNX Runtime 官网查对应版本表,避免版本不匹配。我曾经就吃过亏,装好之后推理结果全错——后来发现是 cuDNN 版本不对。

源码编译(进阶玩家)

为什么要自己编译?三个原因:

  • 需要自定义算子(比如你写了个特殊的激活函数)
  • 需要实验性后端(比如 ONNX Runtime Web)
  • 需要极致优化(针对特定 CPU 指令集)

编译步骤大致如下:

# 1. 克隆仓库
git clone --recursive https://github.com/microsoft/onnxruntime

# 2. 配置构建(以 Linux + CUDA + TensorRT 为例)
cd onnxruntime
./build.sh --config Release \
           --build_shared_lib \
           --use_cuda \
           --cuda_home /usr/local/cuda \
           --cudnn_home /usr/lib/x86_64-linux-gnu/ \
           --use_tensorrt \
           --tensorrt_home /usr/src/tensorrt

# 3. 编译(多核加速)
./build.sh --parallel

如果你要同时支持 OpenVINO,加参数:

--use_openvino /path/to/openvino

Windows 下用 CMake+Visual Studio:

# 在 build 目录下
cmake -G "Visual Studio 16 2019" \
      -A x64 \
      -DONNX_CUDA=ON \
      -DONNX_CUDNN_HOME=... \
      ..
cmake --build . --config Release

编译完会生成 libonnxruntime.so 或 onnxruntime.dll,以及 Python 的 .so/.pyd 文件。然后你就能 import onnxruntime 用了。

注意事项:源码编译耗时很长(我试过在 8 核机器上编译 GPU 版,差不多 40 分钟)。而且 CMake 参数容易写错——我就曾经少写了 --use_tensorrt,结果 RTX 显卡只能用 CUDA 后端,浪费了 TensorRT 加速。建议编译前先跑 ./build.sh --help 看所有选项。

支持后端一览

ONNX Runtime 的核心设计叫 "Execution Provider"(执行提供程序)。每个后端就是一个 EP。你可以在创建 InferenceSession 时指定:

import onnxruntime as ort

# 选择 CUDA 后端
session = ort.InferenceSession(
    "model.onnx",
    providers=['CUDAExecutionProvider', 'CPUExecutionProvider']
)

优先级:数组越靠前越优先。如果 CUDA 不可用,会自动 fallback 到 CPU。以下是常见后端:

后端名称 硬件 特点
CPUExecutionProvider 任意 CPU 通用、稳定、无依赖
CUDAExecutionProvider NVIDIA GPU GPU 基础加速,支持 FP16
TensorrtExecutionProvider NVIDIA GPU TensorRT 优化,极致性能
OpenVINOExecutionProvider Intel CPU/GPU/VPU Intel 平台优化,支持 INT8
DirectMLExecutionProvider DirectX 12 GPU Windows 平台,兼容 AMD/NVIDIA
CoreMLExecutionProvider Apple Neural Engine Mac/iOS 推理加速

经验之谈:我一般在 GPU 机器上同时注册 CUDA 和 TensorRT 两个后端。原因是某些算子在 TensorRT 里不支持(比如动态 shape 很大的场景),fallback 到 CUDA 反而更稳定。你可以在代码里打印支持的 providers 来确认:ort.get_available_providers()。

一张图看懂 ONNX Runtime 生态

下面这张图概括了 ONNX Runtime 的安装路径和后端关系。

ONNX Runtime 安装与后端选择 ONNX Runtime 核心库 pip install onnxruntime pip install onnxruntime-gpu pip install onnxruntime-openvino 源码编译 (./build.sh) 自定义算子 / 实验后端 / 极致优化 CPUExecutionProvider CUDAExecutionProvider TensorrtExecutionProvider OpenVINOExecutionProvider DirectMLExecutionProvider CoreMLExecutionProvider pip 安装适合 90% 的场景

避坑指南与常用命令

讲几个我实际踩过的坑:

  • GPU 版 pip 装完发现只用了 CPU:检查环境变量 CUDA_VISIBLE_DEVICES 有没有被设置,或者 LD_LIBRARY_PATH 没包含 CUDA 库。我曾经被 Docker 里的环境变量坑过整整半天。
  • pip 版本不是最新:有时候你想要新后端,但 pip 上还是旧版。这时候你就得等——或者直接源码编译。我建议关注 ONNX Runtime Release,新后端出来一般 month 内上 pip。
  • 源码编译失败:最常见的是 CMake 权重配置问题。先确认你装了所有依赖:apt install build-essential cmake libprotobuf-dev。然后 ./build.sh --clean 再试。

快速检查安装结果:运行下面代码,看看支持哪些后端:

import onnxruntime as ort
print("可用后端:", ort.get_available_providers())
print("版本:", ort.__version__)

如果输出里没有你想要的(比如 Tensorrt),那就是安装包不对或环境没配好。