重要提示:此資訊僅適用於 ONNX Runtime 1.10 及更早版本。請使用更新的版本。

ONNX Runtime 移動效能調優

瞭解不同最佳化如何影響效能,並獲取使用 ORT 格式模型進行效能測試的建議。

ONNX Runtime Mobile 可用於在 Android 平臺上使用 NNAPI(透過 NNAPI 執行提供程式 (EP))執行 ORT 格式模型,以及在 iOS 平臺上使用 CoreML(透過 CoreML EP)執行模型。

首先,請回顧 在 ONNX Runtime Mobile 中使用 NNAPI在 ONNX Runtime 中使用 CoreML 中的介紹性詳細資訊。

重要提示: 為簡潔起見,本頁中的示例均指 NNAPI EP。此資訊同樣適用於 CoreML EP,因此下文中任何對“NNAPI”的引用都可以替換為“CoreML”。
在 ONNX Runtime 1.9 版本中添加了對建立 CoreML 感知型 ORT 格式模型的支援,類似於建立 NNAPI 感知型 ORT 格式模型

目錄

1. ONNX 模型最佳化示例

ONNX Runtime 會對 ONNX 模型應用最佳化以提高推理效能。這些最佳化在匯出 ORT 格式模型之前發生。有關可用最佳化的更多詳細資訊,請參閱圖最佳化文件。

瞭解不同最佳化級別如何影響模型中的節點非常重要,因為這將決定模型有多少部分可以使用 NNAPI 或 CoreML 執行。

基本

基本最佳化會刪除冗餘節點並執行常量摺疊。在修改模型時,這些最佳化僅使用 ONNX 運算子。

擴充套件

擴充套件最佳化會用自定義的內部 ONNX Runtime 運算子替換一個或多個標準 ONNX 運算子,以提升效能。每個最佳化都有一個適用於它的 EP 列表。它將只替換分配給該 EP 的節點,並且替換的節點將使用相同的 EP 執行。

佈局

佈局最佳化可能是硬體特定的,涉及 ONNX 使用的 NCHW 影像佈局與 NHWC 或 NCHWc 格式之間的內部轉換。它們在最佳化級別設定為“all”時啟用。

  • 對於 ONNX Runtime 1.8 之前的版本,在建立 ORT 格式模型時,不應使用佈局最佳化。
  • 對於 ONNX Runtime 1.8 或更高版本,可以啟用佈局最佳化,因為硬體特定最佳化會自動停用。

建立最佳化後的 ORT 格式模型時的最佳化結果

以下是當僅啟用 CPU EP 並應用於 MNIST 模型時,基本擴充套件最佳化中發生的變化示例。最佳化級別在建立 ORT 格式模型時指定。

  • 基本級別,我們組合了 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
  • 擴充套件級別,我們還使用內部 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 格式模型會發生什麼。

由於基本級別最佳化會生成一個僅使用 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,並使用擴充套件所有級別最佳化建立的 ORT 格式模型
    • ONNX Runtime 1.8 或更高版本使用所有,早期版本使用擴充套件

對於大多數場景,預計這兩種方法之一將產生最佳效能。

如果使用具有基本級別最佳化和 NNAPI 的 ORT 格式模型產生相同或更好的效能,則可能透過建立 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 Runtime,建立一個包含 NNAPI EP 的 ONNX Runtime“完整”構建。

    此構建可在任何平臺上進行,因為 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 感知型 ORT 格式模型,並啟用 NNAPI (--use_nnapi),將最佳化級別設定為擴充套件所有(例如 --optimization_level extended)。這將允許在 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 的最小構建一起使用。