MLIR 編譯器基礎架構中 ONNX 模型的表示和參考降階
此專案由 onnx 維護
託管於 GitHub Pages — 主題由 orderedlist 提供
一般而言,onnx-mlir 將自訂加速器視為外掛程式來處理,這些外掛程式可以在建置 onnx-mlir 和編譯模型時開啟/關閉。處理主要透過 cmake
進行,我們將在此文件中概述其程序。
除了本文之外,NNPA 加速器 可作為在 onnx-mlir 中部署的範例。
在 onnx-mlir 中,加速器的所有程式碼都應放在 src/Accelerators
下的個別資料夾中。因此,支援加速器的第一步是在 src/Accelerators
內為其建立資料夾。
資料夾名稱將在 onnx-mlir 中用作加速器名稱。特別是,它用於
cmake
建置加速器資料夾內的程式碼,onnx-mlir
命令時,為加速器編譯模型,以及onnx-mlir-opt
命令時,啟用與加速器相關的 pass。資料夾內容具有彈性,具體取決於每個加速器。但是,我們建議盡可能遵循與 onnx-mlir
根資料夾相同的結構。這有助於維護整個專案的一致性。
若要在 onnx-mlir 中建置加速器,請在建置 onnx-mlir 時使用 cmake 變數 ONNX_MLIR_ACCELERATORS
。ONNX_MLIR_ACCELERATORS
接受以分號分隔的加速器名稱列表。例如,
$ cd build
$ cmake .. -DONNX_MLIR_ACCELERATORS=accel1;accel2
編譯器命令 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
搭配使用。
每個加速器都需要定義幾個巨集。這些需要包含在 onnx_mlir::accel::Accelerator 中。這些巨集是
INSTRUMENTSTAGE_ENUM_<accel_name>
INSTRUMENTSTAGE_CL_ENUM_<accel_name>
PROFILEIR_CL_ENUM_<accel_name>
OPTREPORT_ENUM_<accel_name>
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
在 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 ®istry) 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-krnl
和 krnl-to-llvm
提供掛鉤。原因是原則上它們是 onnx-mlir 中的第一個和最後一個 pass。Pass onnx-to-krnl
是我們決定哪些 ONNX 運算子將在主機上執行(透過將它們降階到 Krnl 方言)或在加速器上執行(透過將它們降階到為加速器定義的方言)的地方。Pass krnl-to-llvm
是我們將 Krnl 和加速器運算子降階到 LLVM 方言的地方,例如,產生組譯碼或只是呼叫加速器的外部 API。在 onnx-to-krnl
和 krnl-to-llvm
之間,加速器可以有任何方言和 pass。
例如,對於 NNPA 加速器,我們定義 ZHigh 方言,用於 onnx-to-krnl
,並定義 ZLow 方言,用於 krnl-to-llvm
。
加速器的測試應放在資料夾 test 中。特別是,