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

ONNX 运行时移动性能调优

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

ONNX 运行时移动版可以使用 NNAPI (通过 NNAPI 执行提供程序 (EP)) 在 Android 平台上执行 ORT 格式模型,并可以使用 CoreML (通过 CoreML EP) 在 iOS 平台上执行。

首先,请查看 在 ONNX 运行时移动版中使用 NNAPI在 ONNX 运行时中使用 CoreML 中的介绍性详情。

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

目录

1. ONNX 模型优化示例

ONNX 运行时对 ONNX 模型应用优化,以提高推理性能。这些优化发生在导出 ORT 格式模型之前。有关可用优化的更多详情,请参阅图优化文档。

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

基本

基本优化删除冗余节点并执行常量折叠。在修改模型时,这些优化仅使用 ONNX 运算符。

扩展

扩展优化用自定义的内部 ONNX 运行时运算符替换一个或多个标准 ONNX 运算符,以提高性能。每个优化都有一个它有效的 EP 列表。它只会替换分配给该 EP 的节点,并且替换节点将使用相同的 EP 执行。

布局

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

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

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

下面是一个示例,说明当仅启用 CPU EP 时,应用于 MNIST 模型的基本扩展优化中发生的变化。优化级别在创建 ORT 格式模型时指定。

  • 基本级别,我们将 Conv 和 Add 节点组合在一起(加法是通过 Conv 的“B”输入完成的),我们将 MatMul 和 Add 组合成一个 Gemm 节点(加法是通过 Gemm 的“C”输入完成的),并进行常量折叠以删除其中一个 Reshape 节点。
    • python <ORT 仓库根目录>/tools/python/convert_onnx_models_to_ort.py --optimization_level basic /dir_with_mnist_onnx_model
  • 扩展级别,我们还使用内部 ONNX 运行时 FusedConv 运算符融合 Conv 和 Relu 节点。
    • python <ORT 仓库根目录>/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 运行时将加载的模型中的原始节点替换为调用此函数的单个节点。

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

下面是 MNIST 模型的示例,比较了如果注册了 NNAPI EP,运行时 ORT 格式模型会发生什么情况。

由于基本级别的优化导致模型仅使用 ONNX 运算符,因此 NNAPI EP 能够处理模型的大部分,因为 NNAPI 可以执行 Conv、Relu 和 MaxPool 节点。这是通过单个 NNAPI 模型完成的,因为 NNAPI 可以处理的所有节点都已连接。我们期望使用 NNAPI 的模型获得性能提升,因为对于单个 NNAPI 节点,CPU 和 NNAPI 之间的设备复制开销很可能被使用 NNAPI 一次执行多个操作所节省的时间所超过。

扩展级别优化引入了自定义的 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 的情况下,使用基本级别优化创建 ORT 格式模型
  • 在禁用 NNAPI 的情况下,使用扩展all 级别优化创建 ORT 格式模型
    • 对于 1.8 或更高版本的 ONNX 运行时,使用 all,对于以前的版本,使用 extended

对于大多数情况,预计这两种方法之一将产生最佳性能。

如果使用具有基本级别优化的 ORT 格式模型和 NNAPI 产生相当或更好的性能,则可能可以通过创建 NNAPI 感知的 ORT 格式模型来进一步提高性能。此模型与众不同之处在于,更高级别的优化仅应用于无法使用 NNAPI 执行的节点。是否有任何节点属于此类别取决于模型。

3. 创建 NNAPI 感知的 ORT 格式模型

NNAPI 感知的 ORT 格式模型将保留 ONNX 模型中可以使用 NNAPI 执行的所有节点,并允许将扩展优化应用于任何剩余节点。

对于我们的 MNIST 模型,这意味着在应用基本优化后,红色阴影中的节点保持原样,而绿色阴影中的节点可以应用扩展优化。

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

要创建 NNAPI 感知的 ORT 格式模型,请按照以下步骤操作。

  1. 通过从源代码构建 ONNX 运行时,使用 NNAPI EP 创建 ONNX 运行时的“完整”构建。

    此构建可以在任何平台上完成,因为 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 运行时 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)且优化级别设置为扩展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 的最小构建一起使用。