ORT 模型格式

目录

什么是 ORT 模型格式?

ORT 格式是精简版 ONNX Runtime 构建支持的格式。精简版构建可能更适合用于大小受限的环境,例如移动和 Web 应用程序。

完整版 ONNX Runtime 构建支持 ORT 格式模型和 ONNX 模型。

向后兼容性

通常,我们的目标是特定版本的 ONNX Runtime 可以运行当前(ONNX Runtime 发布时)或更旧版本的 ORT 格式模型。

尽管我们努力保持向后兼容性,但仍存在一些重大更改。

ONNX Runtime 版本 ORT 格式版本支持 备注
1.14+ v5, v4 (有限支持) 有关 v4 有限支持的详细信息,请参阅此处
1.13 v5 v5 重大更改:移除了内核定义哈希。
1.12-1.8 v4 v4 重大更改:更新了内核定义哈希计算。
1.7 v3, v2, v1  
1.6 v2, v1  
1.5 v1 ORT 格式引入

将 ONNX 模型转换为 ORT 格式

ONNX 模型使用 convert_onnx_models_to_ort 脚本转换为 ORT 格式。

转换脚本执行两个功能

  1. 加载并优化 ONNX 格式模型,并将其保存为 ORT 格式
  2. 确定优化模型所需的运算符以及可选的数据类型,并将它们保存到配置文件中,以便在需要时用于精简运算符构建

转换脚本可以针对单个 ONNX 模型或目录运行。如果针对目录运行,将递归搜索目录中的“.onnx”文件进行转换。

每个“.onnx”文件都会被加载、优化,并以“.ort”扩展名保存为 ORT 格式文件,保存在与原始“.onnx”文件相同的位置。

脚本输出

  1. 每个 ONNX 模型对应一个 ORT 格式模型
  2. 一个构建配置文件(“required_operators.config”),其中包含优化后的 ONNX 模型所需的运算符。

    如果启用了类型缩减(ONNX Runtime 1.7 版或更高版本),则配置文件还将包含每个运算符所需的类型,并命名为“required_operators_and_types.config”。

    如果您使用的是预构建的 ONNX Runtime iOSAndroidWeb 包,则构建配置文件不会被使用,可以忽略。

脚本位置

ORT 模型格式受 ONNX Runtime 1.5.2 版或更高版本支持。

将 ONNX 格式模型转换为 ORT 格式利用 ONNX Runtime python 包,因为模型会在转换过程中加载到 ONNX Runtime 并进行优化。

对于 ONNX Runtime 1.8 版及更高版本,转换脚本直接从 ONNX Runtime python 包运行。

对于早期版本,转换脚本从本地 ONNX Runtime 仓库运行。

安装 ONNX Runtime

https://pypi.ac.cn/project/onnxruntime/ 安装 onnxruntime python 包,以便将模型从 ONNX 格式转换为内部 ORT 格式。需要 1.5.3 或更高版本。

安装最新发布版本

pip install onnxruntime

安装以前的发布版本

如果您正在从源代码构建 ONNX Runtime(自定义、精简或最小构建),则必须将 python 包版本与您签出的 ONNX Runtime 仓库分支相匹配。

例如,要使用 1.7 版本

git checkout rel-1.7.2
pip install onnxruntime==1.7.2

如果您在 git 仓库中使用 main 分支,您应该使用每夜构建的 ONNX Runtime python 包

pip install -U -i https://test.pypi.org/simple/ ort-nightly

将 ONNX 模型转换为 ORT 格式脚本用法

ONNX Runtime 1.8 或更高版本

python -m onnxruntime.tools.convert_onnx_models_to_ort <onnx model file or dir>

其中

  • onnx model file or dir 是 .onnx 文件或包含一个或多个 .onnx 模型的目录的路径

通过运行带 --help 参数的脚本可以查看当前的可选参数。支持的参数和默认值在 ONNX Runtime 版本之间略有不同。

ONNX Runtime 1.11 的帮助文本

python -m onnxruntime.tools.convert_onnx_models_to_ort --help
  usage: convert_onnx_models_to_ort.py [-h] [--optimization_style {Fixed,Runtime} [{Fixed,Runtime} ...]] [--enable_type_reduction] [--custom_op_library CUSTOM_OP_LIBRARY] [--save_optimized_onnx_model] [--allow_conversion_failures] [--nnapi_partitioning_stop_ops NNAPI_PARTITIONING_STOP_OPS]
                                      [--target_platform {arm,amd64}]
                                      model_path_or_dir

  Convert the ONNX format model/s in the provided directory to ORT format models. All files with a `.onnx` extension will be processed. For each one, an ORT format model will be created in the same directory. A configuration file will also be created containing the list of required
  operators for all converted models. This configuration file should be used as input to the minimal build via the `--include_ops_by_config` parameter.

  positional arguments:
    model_path_or_dir     Provide path to ONNX model or directory containing ONNX model/s to convert. All files with a .onnx extension, including those in subdirectories, will be processed.

  optional arguments:
    -h, --help            show this help message and exit
    --optimization_style {Fixed,Runtime} [{Fixed,Runtime} ...]
                          Style of optimization to perform on the ORT format model. Multiple values may be provided. The conversion will run once for each value. The general guidance is to use models optimized with 'Runtime' style when using NNAPI or CoreML and 'Fixed' style otherwise.
                          'Fixed': Run optimizations directly before saving the ORT format model. This bakes in any platform-specific optimizations. 'Runtime': Run basic optimizations directly and save certain other optimizations to be applied at runtime if possible. This is useful when
                          using a compiling EP like NNAPI or CoreML that may run an unknown (at model conversion time) number of nodes. The saved optimizations can further optimize nodes not assigned to the compiling EP at runtime.
    --enable_type_reduction
                          Add operator specific type information to the configuration file to potentially reduce the types supported by individual operator implementations.
    --custom_op_library CUSTOM_OP_LIBRARY
                          Provide path to shared library containing custom operator kernels to register.
    --save_optimized_onnx_model
                          Save the optimized version of each ONNX model. This will have the same level of optimizations applied as the ORT format model.
    --allow_conversion_failures
                          Whether to proceed after encountering model conversion failures.
    --nnapi_partitioning_stop_ops NNAPI_PARTITIONING_STOP_OPS
                          Specify the list of NNAPI EP partitioning stop ops. In particular, specify the value of the "ep.nnapi.partitioning_stop_ops" session options config entry.
    --target_platform {arm,amd64}
                          Specify the target platform where the exported model will be used. This parameter can be used to choose between platform-specific options, such as QDQIsInt8Allowed(arm), NCHWc (amd64) and NHWC (arm/amd64) format, different optimizer level options, etc.

可选脚本参数

优化方式

自 ONNX Runtime 1.11 起

指定转换后的模型是完全优化(“Fixed”)还是保留运行时优化(“Runtime”)。默认情况下会生成这两种类型的模型。有关更多信息,请参阅此处

这取代了早期 ONNX Runtime 版本中的优化级别选项。

优化级别

ONNX Runtime 1.10 及更早版本

设置 ONNX Runtime 在以 ORT 格式保存模型之前用于优化模型的优化级别。

对于 ONNX Runtime 1.8 及更高版本,如果模型将使用 CPU EP 运行,建议使用 all 级别。

对于早期版本,建议使用 extended 级别,因为 all 级别以前包含设备特定的优化,这会限制模型的移植性。

如果模型要与 NNAPI EP 或 CoreML EP 一起运行,建议使用 basic 优化级别创建 ORT 格式模型。应进行性能测试,比较使用启用 NNAPI 或 CoreML EP 的此模型运行与使用 CPU EP 优化到更高级别的模型运行,以确定最佳设置。

有关更多信息,请参阅关于移动场景性能调优的文档。

启用类型缩减

在 ONNX Runtime 1.7 及更高版本中,可以限制所需运算符支持的数据类型,以进一步减小构建大小。本文件中将此剪枝称为“运算符类型缩减”。当 ONNX 模型转换时,每个运算符所需的输入和输出数据类型将累积并包含在配置文件中。

如果您希望启用运算符类型缩减,则必须安装 Flatbuffers python 包。

pip install flatbuffers

例如,Softmax 的 ONNX Runtime 内核同时支持 float 和 double。如果您的模型使用 Softmax 但仅使用 float 数据,我们可以排除支持 double 的实现,以减小内核的二进制大小。

自定义运算符支持

如果您的 ONNX 模型使用自定义运算符,则必须提供包含自定义运算符内核的库路径,以便成功加载 ONNX 模型。自定义运算符将保留在 ORT 格式模型中。

保存优化后的 ONNX 模型

添加此标志以保存优化后的 ONNX 模型。优化后的 ONNX 模型包含与 ORT 格式模型相同的节点和初始化器,可以在 Netron 中查看,用于调试和性能调优。

以前的 ONNX Runtime 版本

在 ONNX Runtime 1.7 版本之前,模型转换脚本必须从克隆的源代码仓库运行

python <ONNX Runtime repository root>/tools/python/convert_onnx_models_to_ort.py <onnx model file or dir>

加载并执行 ORT 格式模型

执行 ORT 格式模型的 API 与 ONNX 模型相同。

有关单个 API 用法的详细信息,请参阅ONNX Runtime API 文档

各平台 API

平台 可用 API
Android C, C++, Java, Kotlin
iOS C, C++, Objective-C (通过桥接支持 Swift)
Web JavaScript

ORT 格式模型加载

如果您提供 ORT 格式模型的文件名,扩展名为“.ort”的文件将被推断为 ORT 格式模型。

如果您提供 ORT 格式模型的内存中字节,则会检查这些字节中的标记以确定它是否为 ORT 格式模型。

如果您希望明确说明 InferenceSession 输入是 ORT 格式模型,可以通过 SessionOptions 进行设置,尽管这通常不是必需的。

从文件路径加载 ORT 格式模型

C++ API

Ort::SessionOptions session_options;
session_options.AddConfigEntry("session.load_model_format", "ORT");

Ort::Env env;
Ort::Session session(env, <path to model>, session_options);

Java API

SessionOptions session_options = new SessionOptions();
session_options.addConfigEntry("session.load_model_format", "ORT");

OrtEnvironment env = OrtEnvironment.getEnvironment();
OrtSession session = env.createSession(<path to model>, session_options);

JavaScript API

import * as ort from "onnxruntime-web";

const session = await ort.InferenceSession.create("<path to model>");

从内存字节数组加载 ORT 格式模型

如果使用包含 ORT 格式模型数据的输入字节数组创建会话,默认情况下,我们将在会话创建时复制模型字节,以确保模型字节缓冲区有效。

您还可以通过将 SessionOptions 配置项 session.use_ort_model_bytes_directly 设置为 1 来启用直接使用模型字节的选项。这可能会降低 ONNX Runtime Mobile 的峰值内存使用量,但您需要保证模型字节在 ORT 会话的整个生命周期内都是有效的。对于 ONNX Runtime Web,此选项默认启用。

如果启用了 session.use_ort_model_bytes_directly,还有一个选项是直接使用初始化器的模型字节,以进一步降低峰值内存使用量。将 Session Options 配置项 session.use_ort_model_bytes_for_initializers 设置为 1 以启用此功能。请注意,如果某个初始化器被预打包,则会抵消直接使用该初始化器模型字节所带来的峰值内存使用量节省,因为需要为预打包数据分配新的缓冲区。预打包是一种可选的性能优化,涉及将初始化器布局更改为当前平台的最佳顺序(如果不同)。如果降低峰值内存使用量比潜在的性能优化更重要,可以通过将 session.disable_prepacking 设置为 1 来禁用预打包。

C++ API

Ort::SessionOptions session_options;
session_options.AddConfigEntry("session.load_model_format", "ORT");
session_options.AddConfigEntry("session.use_ort_model_bytes_directly", "1");

std::ifstream stream(<path to model>, std::ios::in | std::ios::binary);
std::vector<uint8_t> model_bytes((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());

Ort::Env env;
Ort::Session session(env, model_bytes.data(), model_bytes.size(), session_options);

Java API

SessionOptions session_options = new SessionOptions();
session_options.addConfigEntry("session.load_model_format", "ORT");
session_options.addConfigEntry("session.use_ort_model_bytes_directly", "1");

byte[] model_bytes = Files.readAllBytes(Paths.get(<path to model>));

OrtEnvironment env = OrtEnvironment.getEnvironment();
OrtSession session = env.createSession(model_bytes, session_options);

JavaScript API

import * as ort from "onnxruntime-web";

const response = await fetch(modelUrl);
const arrayBuffer = await response.arrayBuffer();
model_bytes = new Uint8Array(arrayBuffer);

const session = await ort.InferenceSession.create(model_bytes);