Loading...

文章背景图

ONNX Runtime 部署指南:微软跨平台 AI 大模型推理引擎详解

2026-10-29
1
- 字
- 分钟
|

一、ONNX Runtime 是什么:跨平台推理与训练加速器

ONNX Runtime(简称 ORT)是微软推出的一款跨平台、高性能的机器学习推理与训练加速器。它把开放神经网络交换格式(ONNX)模型运行在各种硬件上——从 CPU、NVIDIA GPU、AMD GPU,到手机 NPU、边缘设备——并通过图优化、算子融合、内存规划等手段把推理延迟压到最低。根据官方 README 的描述,ORT 既能加速来自 PyTorch、TensorFlow/Keras 的深度学习模型,也能加速 scikit-learn、LightGBM、XGBoost 等传统机器学习库导出的模型。

ONNX Runtime 官方社交预览图

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 类模型训练。版本徽章:PyPI 版本NuGet 版本

从生态位上看,ORT 介于训练框架与业务应用之间:训练侧开发者不必关心最终部署的硬件是什么,只要导出 ONNX 即可;部署侧工程师则可以在不引入 PyTorch 那套庞大数据栈的前提下,把模型塞进一个几十 MB 的服务容器。这也是为什么微软自己的 ONNX Runtime GenAI 项目能在手机端跑 Llama、Phi 等大语言模型——核心就是 ORT 把模型图编译成了针对移动端硬件高度优化的执行计划。

对企业用户而言,ORT 还有一个常被忽视的价值:统一的模型格式。当团队同时存在 PyTorch、TensorFlow、scikit-learn 多种训练产物时,用 ONNX 作为中间格式可以避免每个业务系统都装一套对应的推理依赖,降低镜像体积与运维成本。

二、环境准备:依赖、硬件与模型格式

2.1 运行时依赖

组件 要求 说明
Python3.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.OnnxRuntimeGenAI

3.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 名称 适用硬件 备注
CPUExecutionProviderx86 / ARM CPU默认,跨平台
CUDAExecutionProviderNVIDIA GPU需 onnxruntime-gpu
TensorrtExecutionProviderNVIDIA GPU进一步图编译优化
DirectMLExecutionProviderWindows 任意 GPUDX12 通用加速
CoreMLExecutionProviderApple Silicon / iOSGPU + ANE 协同
NNAPIExecutionProviderAndroid NPU / GPU端侧推理
OpenVINOExecutionProviderIntel CPU / iGPU / NPUIntel 硬件最优
QNNExecutionProviderQualcomm 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 dynamic

5.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 性能调优要点

  1. 会话复用:InferenceSession 创建开销大,应在进程启动时创建一次,全局复用;
  2. Batch 推理:高并发场景用 dynamic batching,把多个请求合并成一个 batch;
  3. IO 绑定:对输入输出张量预分配固定内存,避免每次推理都 malloc;
  4. 线程数:CPU 推理时 intra_op_num_threads 设为物理核数,inter_op_num_threads 设为 1;
  5. 预热:服务启动后用 dummy 输入跑几次,触发 CUDA kernel 编译与图优化;
  6. 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 自定义算子。解决:

  1. 把 opset_version 提到 17+;
  2. 对自定义算子用 torch.onnx.register_custom_op_symbolic 注册;
  3. 仍不行可考虑 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:如何获取帮助

项目地址:github.com/microsoft/onnxruntime | 开源协议:MIT | 适用场景:模型推理加速、跨硬件部署、LLM 端侧推理、模型量化压缩。

评论交流

文章目录