一、ONNX Runtime 是什么:跨平台推理与训练加速器
ONNX Runtime(简称 ORT)是微软推出的一款跨平台、高性能的机器学习推理与训练加速器。它把开放神经网络交换格式(ONNX)模型运行在各种硬件上——从 CPU、NVIDIA GPU、AMD GPU,到手机 NPU、边缘设备——并通过图优化、算子融合、内存规划等手段把推理延迟压到最低。根据官方 README 的描述,ORT 既能加速来自 PyTorch、TensorFlow/Keras 的深度学习模型,也能加速 scikit-learn、LightGBM、XGBoost 等传统机器学习库导出的模型。
ORT 的核心价值在于:它是一个"推理引擎"而不是一个"训练框架"。开发者可以用任意框架(PyTorch、TensorFlow、Keras、scikit-learn、LightGBM……)训练模型,导出为 ONNX 格式后,用 ORT 在生产环境部署。这样做的好处是:
- 框架解耦:训练侧用 PyTorch,推理侧不需要安装 PyTorch,包体积从 2GB 降到几十 MB;
- 硬件加速:同一行
InferenceSession代码,通过切换 Execution Provider 即可在 CPU / CUDA / TensorRT / CoreML / NNAPI 之间切换; - 量化友好:内置 INT8 / FP16 量化工具链,模型体积可压缩到 1/4 而精度损失极小;
- 多语言:提供 Python、C#、C++、Java、JavaScript、iOS/Android、WinRT 等多套 API。
除了推理,ORT 还提供 ONNX Runtime Training(ORTModule):在 PyTorch 训练脚本里加一行 from onnxruntime.training import ORTModule,就能在多节点 NVIDIA GPU 上加速 Transformer 类模型训练。版本徽章:
从生态位上看,ORT 介于训练框架与业务应用之间:训练侧开发者不必关心最终部署的硬件是什么,只要导出 ONNX 即可;部署侧工程师则可以在不引入 PyTorch 那套庞大数据栈的前提下,把模型塞进一个几十 MB 的服务容器。这也是为什么微软自己的 ONNX Runtime GenAI 项目能在手机端跑 Llama、Phi 等大语言模型——核心就是 ORT 把模型图编译成了针对移动端硬件高度优化的执行计划。
对企业用户而言,ORT 还有一个常被忽视的价值:统一的模型格式。当团队同时存在 PyTorch、TensorFlow、scikit-learn 多种训练产物时,用 ONNX 作为中间格式可以避免每个业务系统都装一套对应的推理依赖,降低镜像体积与运维成本。
二、环境准备:依赖、硬件与模型格式
2.1 运行时依赖
| 组件 | 要求 | 说明 |
|---|---|---|
| Python | 3.9 / 3.10 / 3.11 / 3.12 | 官方发布的 wheel 仅覆盖这几个版本 |
| .NET | .NET 6+ / .NET Framework 4.6.1+ | NuGet 包多目标框架 |
| 操作系统 | Windows 10+ / Ubuntu 20.04+ / macOS 12+ | 移动端另支持 Android 7+、iOS 14+ |
| GPU(可选) | CUDA 11.8 / 12.x、cuDNN 8.x | 仅 onnxruntime-gpu 包需要 |
2.2 准备 ONNX 模型
如果你已经有一个 PyTorch 模型,可以这样导出为 ONNX:
import torch
import torchvision
model = torchvision.models.resnet18(pretrained=True)
model.eval()
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(
model,
dummy_input,
"resnet18.onnx",
input_names=["input"],
output_names=["output"],
dynamic_axes={"input": {0: "batch"}, "output": {0: "batch"}},
opset_version=17,
)
print("exported resnet18.onnx")验证模型:
pip install onnx
python -c "import onnx; m=onnx.load('resnet18.onnx'); onnx.checker.check_model(m); print('OK')"三、安装方式:pip / NuGet / 源码三种路径
3.1 Python 安装(pip)
# CPU 版本(最常用,纯 CPU 推理)
pip install onnxruntime
# GPU 版本(NVIDIA CUDA)
pip install onnxruntime-gpu
# 移动端 / WebAssembly 版本
pip install onnxruntime-web # 浏览器端见官方 npm 包 onnxruntime-web
# GenAI 版本(专门对接大语言模型,内置 beam search / KV cache)
pip install onnxruntime-genai
# 国内镜像
pip install onnxruntime -i https://pypi.tuna.tsinghua.edu.cn/simple验证:
import onnxruntime as ort
print(ort.__version__)
print(ort.get_available_providers())
# 期望输出: ['CPUExecutionProvider'] 或 ['CUDAExecutionProvider', 'CPUExecutionProvider']3.2 .NET 安装(NuGet)
dotnet new console -n OrtDemo
cd OrtDemo
# CPU 推理
dotnet add package Microsoft.ML.OnnxRuntime
# GPU 推理
dotnet add package Microsoft.ML.OnnxRuntime.Gpu
# 移动端(iOS / Android)
dotnet add package Microsoft.ML.OnnxRuntime.Android
dotnet add package Microsoft.ML.OnnxRuntime.Apple
# GenAI(大语言模型)
dotnet add package Microsoft.ML.OnnxRuntimeGenAI3.3 C++ 安装
从 GitHub Releases 下载预编译包(onnxruntime-linux-x64-1.x.x.tgz),解压后把 include/ 与 lib/libonnxruntime.so 加入项目。CMake 示例:
find_path(ORT_INCLUDE_DIR onnxruntime_cxx_api.h)
find_library(ORT_LIB onnxruntime)
target_include_directories(myapp PRIVATE ${ORT_INCLUDE_DIR})
target_link_libraries(myapp PRIVATE ${ORT_LIB})3.4 源码编译(自定义算子 / 裁剪)
git clone --recursive https://github.com/microsoft/onnxruntime.git
cd onnxruntime./build.sh --config Release --build_shared_lib --parallel \
--use_cuda --cuda_home /usr/local/cuda --cudnn_home /usr/local/cuda
# Windows
.\build.bat --config Release --build_shared_lib --use_openvino CPU_FP32源码编译适合需要裁剪算子集、支持自定义 hardware EP、或者把 ORT 嵌入到移动端 App 的场景。
四、快速上手:5 行代码跑通推理
4.1 Python 推理
import onnxruntime as ort
import numpy as np
# 1. 创建会话(首次会加载模型并做图优化)
sess = ort.InferenceSession(
"resnet18.onnx",
providers=["CUDAExecutionProvider", "CPUExecutionProvider"],
)
# 2. 准备输入
input_name = sess.get_inputs()[0].name
output_name = sess.get_outputs()[0].name
dummy_input = np.random.randn(1, 3, 224, 224).astype(np.float32)
# 3. 推理
outputs = sess.run([output_name], {input_name: dummy_input})
print(outputs[0].shape) # (1, 1000)4.2 C# 推理
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
var inputs = new List<NamedOnnxValue> {
NamedOnnxValue.CreateFromTensor("input",
DenseTensor<float>.RandomNormal(new[] { 1, 3, 224, 224 }))
};
using var session = new InferenceSession("resnet18.onnx");
using var results = session.Run(inputs);
var output = results.First().AsEnumerable<float>().ToArray();
Console.WriteLine(output.Length);4.3 用 onnxruntime-genai 跑大语言模型
ORT GenAI 是微软专门为 LLM 推理做的封装,支持 Llama、Phi、Mistral、Gemma 等架构,内置 KV cache、beam search、streaming:
import onnxruntime_genai as og
model = og.Model("path/to/llama-2-7b-onnx/")
tokenizer = og.Tokenizer(model)
prompt = "<|user|>你好,介绍一下你自己<|end|>"
tokens = tokenizer.encode(prompt)
params = og.GeneratorParams(model)
params.set_search_options(max_length=200)
generator = og.Generator(model, params)
generator.append_tokens(tokens)
while not generator.is_done():
generator.generate_next_token()
output = tokenizer.decode(generator.get_sequence())
print(output)五、进阶配置:Execution Provider 与量化
5.1 Execution Provider(硬件加速后端)
ORT 的一大优势是同一模型可以通过切换 EP 跑在不同硬件上。常见 EP:
| EP 名称 | 适用硬件 | 备注 |
|---|---|---|
| CPUExecutionProvider | x86 / ARM CPU | 默认,跨平台 |
| CUDAExecutionProvider | NVIDIA GPU | 需 onnxruntime-gpu |
| TensorrtExecutionProvider | NVIDIA GPU | 进一步图编译优化 |
| DirectMLExecutionProvider | Windows 任意 GPU | DX12 通用加速 |
| CoreMLExecutionProvider | Apple Silicon / iOS | GPU + ANE 协同 |
| NNAPIExecutionProvider | Android NPU / GPU | 端侧推理 |
| OpenVINOExecutionProvider | Intel CPU / iGPU / NPU | Intel 硬件最优 |
| QNNExecutionProvider | Qualcomm NPU | 安卓旗舰芯片 |
5.2 模型量化(INT8 / FP16)
生产环境常用动态量化把模型从 FP32 压到 INT8,体积缩小 4 倍、CPU 推理提速 2-4 倍:
pip install onnxruntime quantization
python -m onnxruntime.quantization.preprocess --input resnet18.onnx --output resnet18_shape.onnx
python -m onnxruntime.quantization.quantize \
--input resnet18.onnx \
--output resnet18_int8.onnx \
--quantization_mode dynamic5.3 图优化级别
sess_options = ort.SessionOptions()
sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
sess_options.intra_op_num_threads = 8
sess_options.enable_cpu_mem_arena = True
sess = ort.InferenceSession("model.onnx", sess_options=sess)六、生产部署:Docker、服务化与性能调优
6.1 Docker 部署
FROM python:3.11-slim
WORKDIR /app
RUN pip install onnxruntime-gpu fastapi uvicorn numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY model.onnx ./
COPY app.py ./
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]app.py(FastAPI 推理服务):
from fastapi import FastAPI
import onnxruntime as ort, numpy as np
app = FastAPI()
sess = ort.InferenceSession("model.onnx", providers=["CUDAExecutionProvider","CPUExecutionProvider"])
@app.post("/predict")
def predict(x: list):
arr = np.array(x, dtype=np.float32)
out = sess.run(None, {sess.get_inputs()[0].name: arr})
return {"result": out[0].tolist()}6.2 性能调优要点
- 会话复用:
InferenceSession创建开销大,应在进程启动时创建一次,全局复用; - Batch 推理:高并发场景用 dynamic batching,把多个请求合并成一个 batch;
- IO 绑定:对输入输出张量预分配固定内存,避免每次推理都 malloc;
- 线程数:CPU 推理时
intra_op_num_threads设为物理核数,inter_op_num_threads设为 1; - 预热:服务启动后用 dummy 输入跑几次,触发 CUDA kernel 编译与图优化;
- Profiling:开启
sess_options.enable_profiling = True生成 timestamps JSON,用 Chrome about:tracing 可视化。
6.3 监控与版本管理
推荐用 MLflow 或 Halo 自己的模型仓库管理 ONNX 文件版本;运行时采集 latency.p50/p95/p99、QPS、GPU 显存占用,接入 Prometheus + Grafana。
6.4 典型生产场景
场景一:电商推荐召回服务。把 PyTorch 训练的双塔模型导出为 ONNX,在 200 台 CPU 机器上通过 ORT 跑批量推理。相比直接用 PyTorch,单容器内存从 1.8GB 降到 350MB,单机 QPS 提升 3 倍。关键优化点是把 embedding 层单独拆出来预计算,线上只跑打分 MLP。
场景二:手机端人像分割。用 CoreMLExecutionProvider 把 ORT 跑在 iPhone 的 ANE(神经引擎)上,模型量化为 FP16 后体积 8MB,单次推理在 iPhone 15 上耗时 12ms,可以实时处理摄像头画面。
场景三:LLM 本地聊天机器人。用 onnxruntime-genai 把 Phi-3 或 Llama-3 量化为 INT4,跑在一台带 RTX 4090 的工作站上,30B 模型可实现每秒 40 个 token 的输出速度,完全离线,不依赖任何云 API。
场景四:金融风控实时打分。LightGBM 训练的反欺诈模型通过 onnxmltools 转 ONNX,在 .NET 业务系统中用 Microsoft.ML.OnnxRuntime 直接调用,单笔交易打分耗时 0.3ms,满足实时风控的 SLA 要求。
七、常见问题 FAQ 与报错处理
Q1:ModuleNotFoundError: No module named 'onnxruntime'
确认已在当前虚拟环境中 pip install onnxruntime。如果同时装了 onnxruntime 和 onnxruntime-gpu,会冲突,建议 pip uninstall onnxruntime onnxruntime-gpu 后重装其中一个。在国内服务器上,PyPI 默认源经常超时,建议使用清华或阿里云镜像:pip install onnxruntime-gpu -i https://mirrors.aliyun.com/pypi/simple/。
Q2:CUDAExecutionProvider 不可用
执行 ort.get_available_providers() 只看到 CPU。常见原因:
- 装的是 CPU 版本(
pip install onnxruntime),需改装onnxruntime-gpu; - 本地 CUDA 版本与 wheel 编译时的 CUDA 版本不匹配(ORT 1.17+ 支持 CUDA 11.8/12.x);
- cuDNN 未安装或不在
LD_LIBRARY_PATH。
排查命令:python -c "import torch; print(torch.version.cuda)" 查看 PyTorch 使用的 CUDA 版本,再去 ORT Release Notes 对照支持矩阵。
Q3:模型导出时报 "Unsupported operator: Foo"
原因:opset 版本过低或用到了 PyTorch 自定义算子。解决:
- 把
opset_version提到 17+; - 对自定义算子用
torch.onnx.register_custom_op_symbolic注册; - 仍不行可考虑
torch.onnx.dynamo_export(Dynamo 导出路径,对新算子支持更好)。
Q4:Could not find ONNX runtime shared library on Windows
NuGet 包安装后未把 DLL 复制到输出目录。在 csproj 中确保:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>Q5:推理延迟忽高忽低
90% 是因为没做 warmup。服务启动后立刻跑 10-20 次 dummy 推理,让 CUDA context、cudnn kernel、内存 arena 都初始化好。
Q6:模型太大(>2GB)加载失败
ONNX 格式默认protobuf 限制 2GB。用外部数据模式:
torch.onnx.export(..., save_as_external_data=True,
all_tensors_to_one_file=True, location="model_weights.bin")Q7:与 TensorRT / OpenVINO 怎么配合
这些 EP 都作为 ORT 的 provider 传入,无需单独安装 SDK 调用。例如 TensorRT:
sess = ort.InferenceSession("model.onnx",
providers=["TensorrtExecutionProvider", "CUDAExecutionProvider", "CPUExecutionProvider"])Q8:如何获取帮助
- 官方文档:onnxruntime.ai/docs
- 示例仓库:microsoft/onnxruntime-inference-examples
- GitHub Issues:microsoft/onnxruntime/issues
- YouTube 教程:@ONNXRuntime
项目地址:github.com/microsoft/onnxruntime | 开源协议:MIT | 适用场景:模型推理加速、跨硬件部署、LLM 端侧推理、模型量化压缩。