在 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
命令时启用与加速器相关的通行证。文件夹内容根据每个加速器而灵活变化。 但是,我们建议尽可能遵循与 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
一起使用。
通过使用选项 --maccel
(类似于 onnx-mlir
中的 --maccel
,请参见第 1.2 节),可以使用 onnx-mlir-opt
命令运行或测试加速器定义的通行证。 例如,要调用加速器 accel1
定义的通行证 --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 中编写代码通常涉及设计方言和通行证。 支持加速器也是如此。 因此,将加速器代码集成到 onnx-mlir 中是在 onnx-mlir 中注册方言和通行证。
我们提供了一个基类 onnx_mlir::accel::Accelerator,用户可以从中定义继承类并编写挂钩来注册方言和通行证。
//===--------------------------------------------------------------------===//
// 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 中有许多通行证,但我们只为两个通行证 onnx-to-krnl
和 krnl-to-llvm
提供挂钩。 原因是,它们原则上是 onnx-mlir 中的第一个和最后一个通行证。 通行证 onnx-to-krnl
是我们可以决定哪些 ONNX 运算符将在主机上运行(通过将它们降低到 Krnl 方言)或在加速器上运行(通过将它们降低到为加速器定义的方言)的地方。 通行证 krnl-to-llvm
是我们将 Krnl 和加速器运算符降低到 LLVM 方言的地方,例如,生成汇编代码或简单地调用加速器的外部 API。 在 onnx-to-krnl
和 krnl-to-llvm
之间可以有任何方言和通行证用于加速器。
例如,对于 NNPA 加速器,我们定义了 ZHigh 方言 用于 onnx-to-krnl
,以及 ZLow 方言 用于 krnl-to-llvm
。
加速器的测试应放在文件夹 test 中。 具体来说,