重要提示:此信息仅适用于 ONNX RUNTIME 1.10 版及更早版本。请使用更新版本。

ONNX Runtime 移动性能调优

了解不同优化如何影响性能,并获取使用 ORT 格式模型进行性能测试的建议。

ONNX Runtime Mobile 可用于在 Android 平台上使用 NNAPI(通过 NNAPI 执行提供者 (EP))执行 ORT 格式模型,以及在 iOS 平台上使用 CoreML(通过 CoreML EP)执行 ORT 格式模型。

首先,请查阅ONNX Runtime Mobile 使用 NNAPIONNX Runtime 使用 CoreML 的介绍性详细信息。

重要提示: 本页面中的示例为简洁起见使用了 NNAPI EP。这些信息同样适用于 CoreML EP,因此下面的任何“NNAPI”引用都可以替换为“CoreML”。
ONNX Runtime 1.9 版添加了创建支持 CoreML 的 ORT 格式模型的功能,类似于创建支持 NNAPI 的 ORT 格式模型

目录

1. ONNX 模型优化示例

ONNX Runtime 会对 ONNX 模型应用优化以提高推理性能。这些优化在导出 ORT 格式模型之前进行。有关可用优化的更多详细信息,请参阅图优化文档。

了解不同优化级别如何影响模型中的节点非常重要,因为这将决定模型有多少部分可以使用 NNAPI 或 CoreML 执行。

Basic (基础)

basic 优化会移除冗余节点并执行常量折叠。在修改模型时,这些优化仅使用 ONNX 算子。

Extended (扩展)

extended 优化会将一个或多个标准 ONNX 算子替换为自定义的 ONNX Runtime 内部算子以提升性能。每种优化都有其适用的 EP 列表。它只会替换分配给该 EP 的节点,并且替换后的节点将使用相同的 EP 执行。

Layout (布局)

Layout 优化可能与硬件相关,并涉及 ONNX 使用的 NCHW 图像布局与 NHWC 或 NCHWc 格式之间的内部转换。它们在优化级别设置为“all”时启用。

  • 对于 1.8 版本之前的 ONNX Runtime,在创建 ORT 格式模型时不应使用 layout 优化。
  • 对于 ONNX Runtime 1.8 版或更高版本,可以启用 layout 优化,因为特定于硬件的优化会自动禁用。

创建优化 ORT 格式模型时的优化结果

下面是将 basic 和 extended 优化应用于仅启用 CPU EP 的 MNIST 模型时发生的变化示例。优化级别在创建 ORT 格式模型时指定。

  • 在 basic 级别,我们将 Conv 和 Add 节点合并(加法通过 Conv 的 'B' 输入完成),我们将 MatMul 和 Add 合并到一个 Gemm 节点中(加法通过 Gemm 的 'C' 输入完成),并通过常量折叠移除其中一个 Reshape 节点。
    • python <ORT repository root>/tools/python/convert_onnx_models_to_ort.py --optimization_level basic /dir_with_mnist_onnx_model
  • 在 extended 级别,我们还使用 ONNX Runtime 内部的 FusedConv 算子融合了 Conv 和 Relu 节点。
    • python <ORT repository root>/tools/python/convert_onnx_models_to_ort.py --optimization_level extended /dir_with_mnist_onnx_model

Changes to nodes from basic and extended optimizations

使用 NNAPI EP 执行优化 ORT 格式模型的结果

如果在运行时注册了 NNAPI EP,它将有机会选择加载模型中它可以执行的节点。这样做时,它会尽可能多地将节点分组在一起,以最大程度地减少在 CPU 和 NNAPI 之间复制数据以执行节点的开销。每组节点都可以视为一个子图。每个子图中的节点越多,子图越少,性能就越好。

对于每个子图,NNAPI EP 将创建一个复制原始节点处理过程的 NNAPI 模型。它将创建一个执行此 NNAPI 模型并执行 CPU 和 NNAPI 之间任何所需数据复制的函数。ONNX Runtime 将把加载模型中的原始节点替换为一个调用此函数的单个节点。

如果 NNAPI EP 未注册或无法处理某个节点,该节点将使用 CPU EP 执行。

下面是 MNIST 模型的一个示例,比较了在运行时注册 NNAPI EP 后 ORT 格式模型会发生什么。

由于 basic 级别的优化生成的模型只使用 ONNX 算子,因此 NNAPI EP 能够处理模型的大部分,因为 NNAPI 可以执行 Conv、Relu 和 MaxPool 节点。这是通过单个 NNAPI 模型完成的,因为所有 NNAPI 可以处理的节点都连接在一起。我们期望使用 NNAPI 可以从这个模型中获得性能提升,因为单个 NNAPI 节点在 CPU 和 NNAPI 之间进行设备复制的开销很可能被使用 NNAPI 同时执行多个操作节省的时间所抵消。

extended 级别的优化引入了自定义的 FusedConv 节点,NNAPI EP 会忽略这些节点,因为它只会处理使用 NNAPI 可以处理的 ONNX 算子的节点。这导致使用 NNAPI 的只有两个节点,每个节点处理一个 MaxPool 操作。这个模型的性能可能会受到不利影响,因为 CPU 和 NNAPI 之间的设备复制开销(在两个 NNAPI 节点之前和之后都需要)不太可能被每次使用 NNAPI 执行单个 MaxPool 操作节省的时间所抵消。通过不注册 NNAPI EP,以便模型中的所有节点都使用 CPU EP 执行,可能会获得更好的性能。

Changes to nodes by NNAPI EP depending on the optimization level the model was created with

2. 初始性能测试

最佳优化设置因模型而异。有些模型使用 NNAPI 可能表现更好,有些则不然。由于性能是模型特定的,您必须运行性能测试来确定最适合您的模型的组合。

建议运行性能测试

  • 启用 NNAPI 并使用 basic 级别优化创建 ORT 格式模型
  • 禁用 NNAPI 并使用 extended 或 all 级别优化创建 ORT 格式模型
    • 对于 ONNX Runtime 1.8 版或更高版本使用 all,对于之前版本使用 extended

在大多数场景下,预计这两种方法中的一种会产生最佳性能。

如果使用 basic 级别优化和 NNAPI 的 ORT 格式模型能够获得同等或更好的性能,则可能通过创建支持 NNAPI 的 ORT 格式模型进一步提高性能。这种模型的区别在于,更高级别的优化仅应用于无法使用 NNAPI 执行的节点。是否存在属于此类别的节点取决于模型。

3. 创建支持 NNAPI 的 ORT 格式模型

支持 NNAPI 的 ORT 格式模型将保留 ONNX 模型中所有可以使用 NNAPI 执行的节点,并允许对任何剩余节点应用 extended 优化。

对于我们的 MNIST 模型,这意味着在应用 basic 优化后,红色阴影区域的节点将保持原样,而绿色阴影区域的节点可以应用 extended 优化。

Show nodes that are preserved as NNAPI can execute them, and nodes that are considered by extended optimizations

请按照以下步骤创建支持 NNAPI 的 ORT 格式模型。

  1. 通过从源文件构建 ONNX Runtime,创建一个包含 NNAPI EP 的“完整”构建版本。

    可以在任何平台进行此构建,因为 NNAPI EP 可以用于创建 ORT 格式模型而无需 Android NNAPI 库,此过程中不涉及模型执行。构建时,如果缺少任何标志,请将 --use_nnapi --build_shared_lib --build_wheel 添加到构建标志中。

    请勿添加 --minimal_build 标志。

    • Windows
        <ONNX Runtime repository root>\build.bat --config RelWithDebInfo --use_nnapi --build_shared_lib --build_wheel --parallel
      
    • Linux
        <ONNX Runtime repository root>/build.sh --config RelWithDebInfo --use_nnapi --build_shared_lib --build_wheel --parallel
      

    注意:对于 ONNX Runtime 1.10 版及更早版本,如果您之前使用精简算子内核进行了最小构建,则需要在执行“完整”构建之前运行 git reset --hard,以确保所有算子内核排除项都被撤销。如果未这样做,您可能因缺少内核而无法加载 ONNX 格式模型。

  2. 从构建输出目录安装 python wheel。
    • Windows:位于 build/Windows/<config>/<config>/dist/<package name>.whl
    • Linux:位于 build/Linux/<config>/dist/<package name>.whl。包名称会因您的平台、python 版本和构建参数而异。<config> 是构建命令中 --config 参数的值。
            pip install -U build\Windows\RelWithDebIfo\RelWithDebIfo\dist\onnxruntime_noopenmp-1.7.0-cp37-cp37m-win_amd64.whl
      
  3. 按照标准说明运行 convert_onnx_models_to_ort.py,启用 NNAPI(--use_nnapi),并将优化级别设置为 extended 或 all(例如 --optimization_level extended),创建支持 NNAPI 的 ORT 格式模型。这将允许在 NNAPI 无法处理的任何节点上运行更高级别的优化。
       python <ORT repository root>/tools/python/convert_onnx_models_to_ort.py --use_nnapi --optimization_level extended /models
    

    必须安装包含 NNAPI 的“完整”构建版本的 python 包,--use_nnapi 才能成为有效选项

    创建的此 ORT 模型可以与包含 NNAPI EP 的最小构建版本一起使用。