onnx-mlir

Logo

在 MLIR 編譯器基礎架構中表示和參考降低 ONNX 模型

在 GitHub 上檢視專案 onnx/onnx-mlir

操作指南

使用 Python 進行推論
使用 C/C++ 進行推論
使用 Java 進行推論

參考文獻

ONNX 方言
OMTensor C99 執行階段 API
OMTensorList C99 執行階段 API
OMTensor Java 執行階段 API
OMTensorList Java 執行階段 API
產生 ONNX 方言
關於文件

開發

新增操作
測試準則
錯誤處理
命令列選項
儀器化
常數傳播
新增加速器

工具

工具

RunONNXModel.py
DocCheck

此專案由 onnx 維護

託管於 GitHub Pages — 主題由 orderedlist 提供

匯入 ONNX 定義並支援操作

目錄

  1. 概述
  2. 新增操作
  3. 自訂操作
  4. 建置
  5. 關於版本的詳細資訊

    概述

    ONNX-MLIR 定義了一個 ONNX 方言來表示 ONNX 指定的操作。ONNX 方言是使用 MLIR 表格產生工具建立的。每個操作的定義都是使用 python 腳本 utils/gen_onnx_mlir.py 從 ONNX 自動轉換而來的。此腳本從 ONNX 套件檢索操作定義,以產生用於方言表格產生的 ONNXOps.td.inc 和用於 ONNX-MLIR 中 ONNX 模型匯入器的 OpBuilderTable.inc。以下章節將描述如何使用 gen_onnx_mlir.py 將操作新增到 ONNX-MLIR 中的 ONNX 方言,以及如何改進操作的定義。

新增操作

若要為 ONNX 方言產生操作,請將此操作新增到 gen_onnx_mlir.py 中的字典 'version_dict' 中。此目錄的鍵是操作名稱,值是此操作的操作集清單。通常僅支援此操作的最高版本操作集(在 onnx-mlir/third_party/onnx 中)。有關版本的詳細資訊,請參閱 版本章節。使用此項目,腳本將為 ONNX 方言產生操作定義。

自訂

新增介面和特徵

預設情況下,所有操作都具有形狀推斷介面和 Pure 特徵。如果操作具有 ResultTypeInferenceOpInterface,請使用字典 OpsWithResultTypeInference。此介面推斷結果張量的類型,而不是形狀。如果操作具有子圖,則它將具有 HasOnnxSubgraphOpInterface 介面。

新增標準化介面

如果轉換應該跨越傳遞在本地應用於操作,則可以使用標準化介面進行此轉換。若要為操作啟用標準化,請將此操作的名稱新增到 OpsWithCanonicalizer 的清單中,然後該操作的定義中將具有 hasCanonicalizer = 1;

自訂建構器

操作的預設建構器需要將結果的類型作為參數。但是,可以推斷結果的類型。自訂建構器可能對簡化程式碼很有用。根據推斷的類型,有兩種類型的建構器:未排序類型和廣播類型。若要為操作啟用特殊建構器,您可以分別將其名稱新增到 custom_builder_unranked_ops_listcustom_builder_broadcast_ops_list 中。

請注意,使用 returnType 可以避免重寫規則中對特殊建構器的需求。請參閱 MLIR 文件ONNX-MLIR 中的範例。將此類類型推斷程式碼移至 ONNXOpHelper.cpp 並擺脫自訂建構器可能是一個更好的解決方案。

請注意,使用 returnType 可以避免重寫規則中對特殊建構器的需求。將此類類型推斷程式碼移至 ONNXOpHelper.cpp 並擺脫自訂建構器可能是一個更好的解決方案。

自訂驗證器

操作的操作描述列出了每個輸入/輸出和屬性的允許類型。表格產生將產生預設驗證器來檢查 IR 的允許類型。如果操作有額外的約束,則應定義自訂驗證器以增強錯誤偵測。例如,操作的兩個輸入可能需要相同的元素類型或相同的等級。此類資訊可以在 ONNX 操作定義中找到,但無法使用方言定義來表示。測試這些約束的最佳方法是在驗證器中。若要將自訂驗證器的介面新增到操作,請在 gen_onnx_mlir.py 中找到下方的陣列,並在其中新增您的操作。

OpsWithVerifier = ['AveragePool', 'Conv', 'InstanceNormalization', 'Mod']

然後,您將在 ONNXOps.td.inc 中的操作定義中找到以下程式碼行

let verifier = [{ return ::verify(*this); }];

當新操作宣告為使用自訂驗證器時,您將需要在 src/Dialect/ONNX/ONNXOps.cpp 中新增實作程式碼。最好查看其他操作以取得一般模式,例如,搜尋 static LogicalResult verify(ONNXInstanceNormalizationOp op)。請注意,每次建立此類操作時,都會執行驗證器。因此,您需要確保它可以與張量和 MemRefs 搭配使用,並且可能與未排序的張量搭配使用。因此,請在適當的情況下保護您的每個測試。例如,一旦張量排序,您就可以驗證等級是否在核准的範圍內(如果存在此類約束);在排序之前,請勿執行此測試。

提示

自訂匯入器

special_op_handler:在 frontend_dialect_transformer.cpp 中建立特殊的匯入函式。目前,特殊處理程式用於具有操作引數的操作

任意額外定義

如果操作的定義需要上述描述之外的額外程式碼,您可以將程式碼放入字典 custom_definition_misc 中。鍵是操作名稱,值是程式碼。

自訂匯入器

special_op_handler:在 frontend_dialect_transformer.cpp 中建立特殊的匯入函式。目前,特殊處理程式用於具有操作引數的操作

任意額外定義

如果操作的定義需要上述描述之外的額外程式碼,您可以將程式碼放入字典 custom_definition_misc 中。鍵是操作名稱,值是程式碼。

建置

為了執行 gen_onnx_mlir.py,必須安裝 ONNX。請參閱 Readme。在您的建置目錄中,執行以下命令。

 make OMONNXOpsIncTranslation

此命令將產生兩個檔案 (src/Dialect/ONNX/ONNXOps.td.inc 和 OpBuilderTable.inc),並將其複製到 src 目錄中的正確位置。如果您修改了 gen_onnx_mlir.py,您也需要檢查兩個產生的檔案。它們在 ONNX-MLIR 建置中被視為原始檔案,因此 ONNX-MLIR 的使用者不需要安裝特定版本的 ONNX。請勿直接修改這些檔案。您也可以使用在 utils 目錄中產生的檔案直接執行腳本。 python ../utils/gen_onnx_mlir.py

更新文件

當新增新的 op 版本或變更 ONNX 版本時,我們也希望在我們支援的操作的 ONNX 文件中反映這些變更。雖然最新的 ONNX 規格 始終可用,但我們支援的規格通常會稍微落後一點,而且我們還會根據上一節提到的版本化名稱支援較舊的版本。

有一個方便的命令可以更新 ONNX 和 Krnl 方言,如下所示。

make onnx-mlir-docs

上述命令在通常的 build 目錄中執行,它會將新的方言 md 檔案直接安裝到 docs/Dialects 目錄中。

當新增操作/變更 Krnl 方言時,應該使用相同的命令。

操作版本

ONNX-MLIR 專案是在 ONNX 版本為 1.7.0 時啟動的,並且不打算向後相容。我們依靠 onnx/converter 將模型轉換為 ONNX-MLIR 支援的版本。隨著 ONNX 版本的發展,ONNX-MLIR 嘗試跟進,但可能會落後於最新版本。

操作版本

如先前所述,我們嘗試支援最新版本的 ONNX 操作。目前支援的每個操作的版本都記錄在 utils/gen_onnx_mlir.py 中。此機制提供了一些版本穩定性。若要檢查版本中的變更,請使用標誌「–check-version」執行 gen_onnx_mlir.py,並將報告變更。若要移至較新的版本,請手動更新腳本中的版本字典。

支援多個版本

若要支援 op 的多個版本,應將選取的版本新增到 utils/gen_onnx_mlir.py 中的版本字典中。例如,對於 ReduceSum,支援兩個版本(opset):11 和 13。version_dic 中的對應項目是 'ReduceSum': [13, 11]

在 ONNX 方言中,最高版本的 op 在 op 名稱中沒有版本,而其他版本則帶有名稱,後跟 'V' 和版本號碼。例如,opset 13 的 ReduceSum 將是 ONNXReduceSumOp,而 opset 11 的 ReduceSum 是 'ONNXReduceSumV11Op'。由於大多數 ONNX op 在升級到更高版本時都相容,因此我們可以保留方言中操作的名稱,只需更新 gen_onnx_mlir.py 中的 version_dict,而無需修改 ONNX-MLIR 中的程式碼。

匯入模型時,會使用不超過下一個可用版本的最高版本。對於 ReduceSum 的範例,如果 opset 為 12,則會選取 ONNXReduceSumV11Op。

移轉

要遷移新的 ONNX 版本,首先必須升級 third_part/onnx 以及您的 ONNX 安裝。接著,您可以使用 --check_operation_version 標籤來執行 gen_onnx_mlir.py。所有運算的最高版本將會輸出為新的 version_dict。如果某個運算的介面沒有改變(根據 ONNX 的變更文件),您可以直接使用新版本。如果介面有變更,您可以將新版本插入版本列表的第一個位置。對於現有的程式碼,所有相關的程式碼都必須修改。舉例來說,當 ReduceSum 從版本 11 移至版本 13 時,ONNXReduceSumOp 會先被取代為 ONNXReduceSumOpV11。然後,版本 13 的程式碼將使用 ONNXReduceSumOp。這樣設計的原因是大多數的 ONNX 變更不會改變介面。我們不希望增加開發人員的負擔,讓他們必須記住使用哪個版本的運算,除非絕對必要。並非總是需要保留舊版本的程式碼,舊版本程式碼可能會被重寫為新的運算。因此,我們只需要有方言定義,而不需要推論或降低的程式碼。