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-mlir 將自訂加速器視為外掛程式來處理,這些外掛程式可以在建置 onnx-mlir 和編譯模型時開啟/關閉。處理主要透過 cmake 進行,我們將在此文件中概述其程序。

除了本文之外,NNPA 加速器 可作為在 onnx-mlir 中部署的範例。

1. 程式碼資料夾

在 onnx-mlir 中,加速器的所有程式碼都應放在 src/Accelerators 下的個別資料夾中。因此,支援加速器的第一步是在 src/Accelerators 內為其建立資料夾。

資料夾名稱將在 onnx-mlir 中用作加速器名稱。特別是,它用於

  1. 指示 cmake 建置加速器資料夾內的程式碼,
  2. 在使用 onnx-mlir 命令時,為加速器編譯模型,以及
  3. 在使用 onnx-mlir-opt 命令時,啟用與加速器相關的 pass。

資料夾內容具有彈性,具體取決於每個加速器。但是,我們建議盡可能遵循與 onnx-mlir 根資料夾相同的結構。這有助於維護整個專案的一致性。

1.1 在 onnx-mlir 中建置加速器

若要在 onnx-mlir 中建置加速器,請在建置 onnx-mlir 時使用 cmake 變數 ONNX_MLIR_ACCELERATORSONNX_MLIR_ACCELERATORS 接受以分號分隔的加速器名稱列表。例如,

$ cd build
$ cmake .. -DONNX_MLIR_ACCELERATORS=accel1;accel2

1.2 編譯模型以使用選定的加速器執行。

編譯器命令 onnx-mlir 有一個選項,即 --maccel,可用於編譯模型以供選定的加速器使用。針對每個加速器新增一個 --maccel=accel_name 項目。例如,

$ onnx-mlir --maccel=accel1 --maccel=accel2 model.onnx

只有已建置的加速器才能與 --maccel 搭配使用。

加速器定義的 pass 可以透過 onnx-mlir-opt 命令使用選項 --maccel 來執行或測試,這與 onnx-mlir 中的 --maccel 類似(請參閱第 1.2 節)。例如,若要呼叫加速器 accel1 定義的 pass --optimize-data-layout

$ onnx-mlir-opt --maccel=accel1 --optimize-data-layout model.mlir

只有已建置的加速器才能與 --maccel 搭配使用。

2. 程式碼整合

2.1 巨集

每個加速器都需要定義幾個巨集。這些需要包含在 onnx_mlir::accel::Accelerator 中。這些巨集是

  1. INSTRUMENTSTAGE_ENUM_<accel_name>
  2. INSTRUMENTSTAGE_CL_ENUM_<accel_name>
  3. PROFILEIR_CL_ENUM_<accel_name>
  4. OPTREPORT_ENUM_<accel_name>
  5. OPTREPORT_CL_ENUM_<accel_name>

<accel_name> 替換為加速器的名稱,例如,如果您的加速器命名為 ACCEL1,則使用

#define INSTRUMENTSTAGE_ENUM_ACCEL1
#define INSTRUMENTSTAGE_CL_ENUM_ACCEL1
#define PROFILEIR_CL_ENUM_ACCEL1
#define OPTREPORT_ENUM_ACCEL1
#define OPTREPORT_CL_ENUM_ACCEL1

2.2 方言和 pass

在 MLIR 中編寫程式碼通常涉及設計方言和 pass。支援加速器也是如此。因此,將加速器程式碼整合到 onnx-mlir 中就是在 onnx-mlir 中註冊方言和 pass。

我們提供一個基底類別 onnx_mlir::accel::Accelerator,使用者可以從中定義繼承的類別,並編寫掛鉤以註冊方言和 pass。

//===--------------------------------------------------------------------===//
// Hooks for onnx-mlir driver
//===--------------------------------------------------------------------===//

/// Add the transformations necessary to support the accelerator.
virtual void addPasses(mlir::OwningOpRef<mlir::ModuleOp> &module,
    mlir::PassManager &pm,
    onnx_mlir::EmissionTargetType &emissionTarget) const = 0;

//===--------------------------------------------------------------------===//
// Hooks for onnx-mlir-opt driver
//===--------------------------------------------------------------------===//

/// Register the MLIR dialects required to support an accelerator.
virtual void registerDialects(mlir::DialectRegistry &registry) const = 0;

/// Register accelerator transformation passes to make available as
/// command line options.
virtual void registerPasses(int optLevel) const = 0;

//===--------------------------------------------------------------------===//
// Hooks for onnx-to-krnl pass
//===--------------------------------------------------------------------===//

/// Convert TensorType to MemRefType.
/// Acccelators may have special versions of TensorType. If not, override this
/// method and return nullptr.
virtual mlir::MemRefType convertTensorTypeToMemRefType(
    const mlir::TensorType tensorType) const = 0;

/// Define conversion target to be used with ONNXToKrnl.
virtual void conversionTargetONNXToKrnl(
    mlir::ConversionTarget &target) const = 0;

/// Define rewrite patterns to be used with ONNXToKrnl.
virtual void rewritePatternONNXToKrnl(mlir::RewritePatternSet &patterns,
    mlir::TypeConverter &typeConverter, mlir::MLIRContext *ctx) const = 0;

//===--------------------------------------------------------------------===//
// Hooks for krnl-to-llvm pass
//===--------------------------------------------------------------------===//

/// Define conversion target to be used with KrnlToLLVM.
virtual void conversionTargetKrnlToLLVM(
    mlir::ConversionTarget &target) const = 0;

/// Define rewrite patterns to be used with KrnlToLLVM.
virtual void rewritePatternKrnlToLLVM(mlir::RewritePatternSet &patterns,
    mlir::LLVMTypeConverter &typeConverter, mlir::MLIRContext *ctx) const = 0;

雖然在 onnx-mlir 中有很多 pass,但我們只為兩個 pass onnx-to-krnlkrnl-to-llvm 提供掛鉤。原因是原則上它們是 onnx-mlir 中的第一個和最後一個 pass。Pass onnx-to-krnl 是我們決定哪些 ONNX 運算子將在主機上執行(透過將它們降階到 Krnl 方言)或在加速器上執行(透過將它們降階到為加速器定義的方言)的地方。Pass krnl-to-llvm 是我們將 Krnl 和加速器運算子降階到 LLVM 方言的地方,例如,產生組譯碼或只是呼叫加速器的外部 API。在 onnx-to-krnlkrnl-to-llvm 之間,加速器可以有任何方言和 pass。

例如,對於 NNPA 加速器,我們定義 ZHigh 方言,用於 onnx-to-krnl,並定義 ZLow 方言,用於 krnl-to-llvm

3. 測試

加速器的測試應放在資料夾 test 中。特別是,