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 命令时启用与加速器相关的通行证。

文件夹内容根据每个加速器而灵活变化。 但是,我们建议尽可能遵循与 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 一起使用。

通过使用选项 --maccel(类似于 onnx-mlir 中的 --maccel,请参见第 1.2 节),可以使用 onnx-mlir-opt 命令运行或测试加速器定义的通行证。 例如,要调用加速器 accel1 定义的通行证 --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 方言和通行证

在 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 &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 中有许多通行证,但我们只为两个通行证 onnx-to-krnlkrnl-to-llvm 提供挂钩。 原因是,它们原则上是 onnx-mlir 中的第一个和最后一个通行证。 通行证 onnx-to-krnl 是我们可以决定哪些 ONNX 运算符将在主机上运行(通过将它们降低到 Krnl 方言)或在加速器上运行(通过将它们降低到为加速器定义的方言)的地方。 通行证 krnl-to-llvm 是我们将 Krnl 和加速器运算符降低到 LLVM 方言的地方,例如,生成汇编代码或简单地调用加速器的外部 API。 在 onnx-to-krnlkrnl-to-llvm 之间可以有任何方言和通行证用于加速器。

例如,对于 NNPA 加速器,我们定义了 ZHigh 方言 用于 onnx-to-krnl,以及 ZLow 方言 用于 krnl-to-llvm

3. 测试

加速器的测试应放在文件夹 test 中。 具体来说,