Dialect及Operation详解

article/2025/10/13 20:28:02

参考资料:

[MLIR] Dialect及Operation详解 - 知乎 (zhihu.com)

2.  Dialect 及Operation

2.1Dialect

2.1.1Dialect 是什么?

从源程序到目标程序,要经过一系列的抽象以及分析,通过 Lowering Pass 来实现从一个IR到另一个IR的转换。但IR之间的转换需要统一格式,统一IR的第一步就是要统一“语言”,各个IR原来配合不默契,谁也理解不了谁,就是因为“语言”不通。

因此 MLIR 提出了Dialect,各种IR可以转换为对应的 mlir Dialect,不仅方便了转换,而且还能随意扩展。不妨将dialect看成各种具有IR表达能力的黑盒子,之后的编译流程就是在各种dialect之间转化。

2.1.2 dialect 是怎么工作的?

MLIR中的Dialect可以看作是一种扩展机制,它可以用于表示不同的编程语言和领域特性。在MLIR中,每个Dialect都会定义自己的语法规则和操作,这些规则和操作可以用于构建对应的IR表示。为了避免命名冲突,MLIR将不同的Dialect的IR定义在不同的命名空间中。

每种语言的 dialect(如tensorflow dialect、HLO dialect、LLVM IR dialect)都是继承自 mlir::Dialect,并注册了数字自己的属性、操作和数据类型,也可以使用虚函数来改变一些通用性行为

整个的编译过程:从源语言生成 AST(Abstract Syntax Tree,抽象语法树),借助 dialect 遍历 AST,产生 MLIR 表达式(此处可为多层IR通过 Lowering Pass 依次进行分析),最后经过 MLIR 分析器,生成目标硬件程序。

2.1.3. dialect 内部构成

dialect主要是由自定义的 TypeAttributeInterface 以及 operation 构成。operation 细分为Attribute、Type、Constraint、Interface、Trait(属性、类型、限制、接口、特征)。同时存在 ODS 和 DRR 两个重要的模块,这两个模块都是基于 tableGen 模块,ODS 模块用于定义 operation ,DRR 模块用于实现两个 dialect 之间的 conversion

2.2 Operation

Operation 是 Dialect 的重要组成部分,是抽象和计算的核心单元,可以看成是方言语义的基本元素

下面例子可理解为:

生成的结果是 %t_tensor,toy dialect,执行的是 transpose 操作,输入数据是 %tensor,能够将 tensor<2x3xf64> 的数据转换成tensor<3x2xf64> 的数据,该 transpose 的位置在 "example/file/path",第12行,第1个字符:

%t_tensor = "toy.transpose"(%tensor) {inplace = true} : (tensor<2x3xf64>) -> tensor<3x2xf64> loc("example/file/path":12:1)

结构拆分解析:

(1)%t_tensor:定义结果名称,SSA值,由%<t_tensor>构成,一般<t_tensor>是一个整数型数字。

IR 是 LLVM 的设计核心,它采用 SSA(Single-Static Assignments,静态单赋值)的形式,并具备两个重要特性:
- 代码被组织成三地址指令
- 有无限的寄存器

(2)"toy.transpose":操作的名称,应该是唯一的字符串,方言空间以.开头;指明为 Toy Dialect 的transpose 操作;.之前的内容是 Dialect 命名空间的名字,.后面是操作的名称。

(3)(%tensor):输入的操作数的列表,多个操作数之间用逗号隔开。

(4){inplace = true}:属性字典,定义一个名为inplace的布尔类型,其常量值为true

(5)(tensor<2x3xf64>) -> tensor<3x2xf64>:函数形式表示的操作类型,前者是输入,后者是输出。<2x3xf64>号中间的内容描述了张量的尺寸2x3和张量中存储的数据类型f64,中间使用x连接。

(6)loc("example/file/path":12:1):此操作的源代码中的位置。每个操作都有与之关联的强制性源位置,在 MLIR 中是核心要求,并且 API 依赖并操纵他。例如:如果一个转换将操作替换成另一个操作,必须在新的操作中附加一个位置,可以追踪该操作的来源。所以,在使用工具链 mlir-opt 中默认没有这个位置信息,添加 -mlir-print-debuginfo 标志指定要包含位置。

更一般的格式可见下图:

3. 创建新的dialect(添加新的operation)

本节创建新的dialect包括 手动编写C++创建 以及 利用ODS框架生成

ODS 全称 Operation Definition Specification,操作者只需要根据 operation 框架定义的规范,在一个 .td文件中填写相应的内容,使用 mlir 的 tableGen 工具就可以自动生成上面的 C++ 代码。
本节完全参考官方文档 : Chapter 2: Emitting Basic MLIR - MLIR (llvm.org)

本节将以Toy语言为例,演示构造 Toy Dialect并添加相应的Operation的流程。

Toy语言是为了验证及演示MLIR系统的整个流程而开发的一种基于Tensor的语言。
Toy 语言具有以下特性:
- Mix of scalar and array computations, as well as I/O
- Array shape Inference
- Generic functions
- Very limiter set of operators and features

3.1 定义 Toy Dialect

Dialect 将对 Toy 语言的结构进行建模,并为高级分析和转换提供方便的途径。

3.1.1. 使用 C++ 语言手动编写

// 下面是官方给出的Toy Dialect定义,默认位置为 ../mlir/examples/toy/Ch2/include/toy/Dialect.h
class ToyDialect : public mlir::Dialect {
public:explicit ToyDialect(mlir::MLIRContext *ctx);/// Provide a utility accessor to the dialect namespace.static llvm::StringRef getDialectNamespace() { return "toy"; }/// An initializer called from the constructor of ToyDialect that is used to/// register attributes, operations, types, and more within the Toy dialect.void initialize();
};

3.1.2. 使用 ODS 框架自动生成

在使用 ODS 定义操作的这些代码,都在 Ops.td中,默认位置为 ../mlir/examples/toy/Ch2/include/toy/Ops.td

下面的代码块定义一个名字为 Toy 的 Dialect 在 ODS 框架中,使用let <...> = "..."/[{...}];方式依次明确 name、summary、description 和 cppNamespace(对应 Dialect 类所在的 C++ 命名空间)各个字段的定义。

def Toy_Dialect : Dialect {// The namespace of our dialect, this corresponds 1-1 with the string we// provided in `ToyDialect::getDialectNamespace`.let name = "toy";// A short one-line summary of our dialect.let summary = "A high-level dialect for analyzing and optimizing the ""Toy language";// A much longer description of our dialect.let description = [{The Toy language is a tensor-based language that allows you to definefunctions, perform some math computation, and print results. This dialectprovides a representation of the language that is amenable to analysis andoptimization.}];// The C++ namespace that the dialect class definition resides in.let cppNamespace = "toy";
}

然后在编译阶段,由框架自动生成相应的 C++ 代码。当然也可以运行下面的命令 直接得到生成的 C++ 代码。

${build_root}/bin/mlir-tblgen -gen-dialect-decls ${mlir_src_root}/examples/toy/Ch2/include/toy/Ops.td -I ${mlir_src_root}/include/

下图中右侧是 ODS 中的定义,左侧是自动生成的 C++ 代码。

3.2 加载到 MLIRContext 中

定义好 Dialect 之后,需要将其加载到 MLIRContext 中。默认情况下,MLIRContext 只加载内置的 Dialect,若要添加自定义的 Dialect,需要加载到 MLIRContext。 

// 此处的代码与官方文档中的稍有不同,但实际意义相同。
// 在代码文件 toyc.cpp 中,默认位置为 ../mlir/examples/toy/Ch2/toyc.cpp。
int dumpMLIR() {
...// Load our Dialect in this MLIR Context.context.getOrLoadDialect<mlir::toy::ToyDialect>();
...
}

3.3 定义 operation

有了上述的 Toy Dialect,便可以定义操作(operation)。官方文档围绕 Toy toy.ConstantOp 的定义介绍如何使用 C++ 的方式直接定义 operation。

# 此操作没有输入,返回一个常量。
%4 = "toy.constant"() {value = dense<1.0> : tensor<2x3xf64>} : () -> tensor<2x3xf64>

3.3.1使用 C++ 语言手动编写

operation 类是继承于 CRTP 类,有一些可选的 traits 来定义行为。下面是 ConstantOp 的官方定义:

// `mlir::Op` is a CRTP class
class ConstantOp : public mlir::Op<ConstantOp, // The ConstantOp mlir::OpTrait::ZeroOperands, // takes zero input operandsmlir::OpTrait::OneResult, // returns a single result.mlir::OpTraits::OneTypedResult<TensorType>::Impl> {public:// Op inherit the constructors from the base Op class.using Op::Op; // Return a unique name of the operationstatic llvm::StringRef getOperationName() { return "toy.constant"; }// Return a value by fetching it from the attributemlir::DenseElementsAttr getValue(); // Operations may provide additional verification beyond what the attached traits provide.LogicalResult verifyInvariants(); // Provide an interface to build this operation from a set of input values.// mlir::OpBuilder::create<ConstantOp>(...)// Build a constant with the given return type and `value` attribute.static void build(mlir::OpBuilder &builder, mlir::OperationState &state,mlir::Type result, mlir::DenseElementsAttr value);// Build a constant and reuse the type from the given 'value'.static void build(mlir::OpBuilder &builder, mlir::OperationState &state,mlir::DenseElementsAttr value);// Build a constant by broadcasting the given 'value'.static void build(mlir::OpBuilder &builder, mlir::OperationState &state,double value);
};

 定义好 operation 的行为后,我们可以在 Toy Dialect 的 initialize 函数中注册(register),之后才可以正常在 Toy Dialect 中使用 ConstantOp。

// 位于../mlir/examples/toy/Ch2/mlir/Dialect.cpp
void ToyDialect::initialize() {addOperations<ConstantOp>();
}

3.3.2 使用 ODS 框架自动生成

首先在 ODS 中定义一个继承自 Op 类的基类 Toy_Op

Operation 和 Op的区别 Operation:用于对所有操作的建模,并提供通用接口给操作的实例。 Op:每种特定的操作都是由 Op 类继承来的。同时它还是 Operation * 的 wrapper,这就意味着,当我们定义一个 Dialect 的 Operation 的时候,我们实际上是在提供一个 Operation 类的接口。
Op 类的定义在 OpBased.td 文件中,默认位置为 ../mlir/include/mlir/IR/OpBased.td。
下面的代码都在 Ops.td中,默认位置为 ../mlir/examples/toy/Ch2/include/toy/Ops.td
class Toy_Op<string mnemonic, list<OpTrait> traits = []> :Op<Toy_Dialect, mnemonic, traits>;
// Toy_Dialect : 父类 Dialect 操作
// mnemonic : 注记符号,一般是一个字符串型的单词,代表了该操作的含义
// traits : 该操作的一些特征,放在一个列表中

 其次以声明的方式定义相应操作:

def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {// "constant"就是注记符号,[NoSideEffect]说明了该操作的一个特点// Provide a summary and description for this operation. let summary = "constant";let description = [{Constant operation turns a literal into an SSA value. The data is attachedto the operation as an attribute. For example:```mlir%0 = toy.constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]>: tensor<2x3xf64>```}];/*arguments和results:定义参数和结果,参数可以是SSA操作数的属性或类型。通过为参数或结果提供名称,ODS将自动的生成匹配的访问器。arguments一般模板(results同理): let arguments = (ins <data_type><data_attribute>:$<variable_name>);- ins: 输入 (results中该参数为 outs)- <data_type>: 数据类型- <data_structure>: 数据属性- ElementsAttr: 稠元(dense element)- <variable_name>: 变量名*/// The constant operation takes an attribute as the only input.// `F64ElementsAttr` corresponds to a 64-bit floating-point ElementsAttr.let arguments = (ins F64ElementsAttr:$value);// The constant operation returns a single value of TensorType.let results = (outs F64Tensor);// Divert the printer and parser to `parse` and `print` methods on our operation.let hasCustomAssemblyFormat = 1;/*// 自定义程序的组装格式,使最终输出的 IR 格式更精简、易读let parser = [{ return ::parseConstantOp(parser, result); }];let printer = [{ return ::print(p, *this); }];*/// ODS 可以自动生成一些简单的构建方法,用户也可自定义添加一些构造方法let builders = [// Build a constant with a given constant tensor value.OpBuilderDAG<(ins "DenseElementsAttr":$value), [{build($_builder, $_state, value.getType(), value);}]>,// Build a constant with a given constant floating-point value.OpBuilderDAG<(ins "double":$value)>];// Add additional verification logic to the constant operation.// will generate a `::mlir::LogicalResult verify()`let hasVerifier = 1;
}

 然后在编译阶段,由框架自动生成相应的 C++ 代码。当然也可以运行下面的命令 直接得到生成的 C++ 代码。

${build_root}/bin/mlir-tblgen -gen-op-defs ${mlir_src_root}/examples/toy/Ch2/include/toy/Ops.td -I ${mlir_src_root}/include/

 下图中右侧是 ODS 中的定义,左侧是自动生成的 C++ 代码。

官方的文档在这时候没提及需要在 Toy Dialect 的 initialize 函数中注册生成的Op

3.4 创建流程总结(使用ODS)

整个 tableGen 模块是基于 ODS (Operation Definition Specification)框架进行编写以及发挥作用。tableGen 模块促进了自动化生成,减少了 operation 的手动开发,并且避免了冗余开发。

我们以添加 Toy Dialect为例,总结添加流程如下:

我们以添加 Toy Dialect为例,总结添加流程如下:

① (在Ops.td中) 定义一个和 Toy Dialect 的链接

def Toy_Dialect : Dialect {let name = "toy";...let cppNamespace = "toy";
}

② (在Ops.td中) 创建 Toy Dialect Operation 基类

class Toy_Op<string mnemonic, list<OpTrait> traits = []> :Op<Toy_Dialect, mnemonic, traits>;

③ (在Ops.td中) 创建 Toy Dialect 中各种 Operation

def ConstantOp : Toy_Op<"constant", [NoSideEffect]> {let summary = "constant";let arguments = (ins F64ElementsAttr:$value);let results = (outs F64Tensor);let builders = [OpBulider<"Builder *b, OperationState &state, Value input">];let verifier = [{ return ::verify(*this); }];
}

④ 通过 mlir-tblgen 工具生成 C++ 文件

使用 mlir-tblgen -gen-dialect-decls 命令生成对应的 Dialect.h.inc 文件。

使用 mlir-tblgen -gen-op-defs 命令生成对应的 Ops.h.inc 文件。

 使用 #include 直接引用生成文件

#include "toy/Dialect.h.inc"
#include "toy/Ops.h.inc"

http://chatgpt.dhexx.cn/article/lhFJryFV.shtml

相关文章

神州战神笔记本开启/关闭键盘背光灯的方法,control center使用配置,控制风扇转速,减少噪音

control center控制噪音是有效的。windows更新后&#xff0c;需要重新打开control center。 1、control center路径&#xff1a; c:\Program Files\Hotkey或c:\Program Files(x86)\Hotkey目录下。 2、进入配置界面&#xff1a; 3、调整风扇转速&#xff0c;控制噪音&#xff…

笔记本电脑键盘颜色不切换及control center打不开问题解决方法

文章目录 问题描述解决方法对于键盘颜色不切换control center打不开 问题描述 我的雷神笔记本电脑&#xff0c;出现开机时&#xff0c;键盘颜色不切换&#xff0c;重新安装驱动后control center打不开&#xff0c;虽然感觉这个键盘颜色不太影响我的使用&#xff0c;但是就是不…

打印机添加或者设置流程

作者&#xff1a;蓝眼泪 这里以震旦打印机的添加作为参考 环境准备&#xff1a;xp&#xff0c;win7或者win10操作系统&#xff0c;震旦打印机驱动。 1 开始 运行 输入命令 control 2 选择类别&#xff0c;打印机 3 添加打印机-我需要的打印机未列出&#xff0c;tcp/it,下一步…

linux运行mate,在Ubuntu MATE系统上自动启动程序的方法

Mate桌面环境有很多设置,用户可以利用这些设置进行自定义,本文要讲的是自动启动功能,因为它允许用户自动启动Ubuntu MATE上的程序,可以决定Ubuntu MATE系统如何加载程序,脚本甚至服务。在Mate桌面上配置自动启动功能是通过系统设置完成的。如果需要启用系统自动登陆,请参…

访问 的请求遭到拒绝_服务器端请求伪造(SSRF)攻击导致大量科技、工业和媒体组织信息泄露...

摘要 服务器端请求伪造(SSRF)是一个Web应用程序漏洞&#xff0c;可将攻击者的请求重定向到防火墙后的内部网络或本地主机。由于使用了元数据API&#xff0c;因此SSRF对云服务构成了特殊的威胁&#xff0c;这些元数据API允许应用程序访问底层云基础架构的信息&#xff0c;例如配…

【控制中心】让你的 Mac 系统更方便

macOS 11 中新加入的功能 - 【控制中心】。 虽然说是 Mac 新加入的功能&#xff0c;不过使用 iPhone 和 iPad 的朋友其实早就用到这个功能了。 【控制中心】是将之前散落在系统各处的控制功能集中在一处&#xff0c;方便用户使用&#xff0c;这个功能显然非常重要&#xff0c…

windows下运行 jar包后台运行以及杀死后台进程

比如要运行该jar包 输入命令 java -jar demo-0.0.1-SNAPSHOT.jar 如果端口被占用&#xff1f;&#xff1f;&#xff1f;&#xff1f;这个初学者经常碰到 cmd 查找指定端口比如8080 netstat -aon | findstr "8080" 杀死pid为23604的进程 tasklist|findstr "23…

ssh远程登录遇到的一系列问题

1.报的啥错我不记得了&#xff0c;有一个refuse 确认一下win10的ssh客户端和服务器都安装、启动了没。 2.用Xshell登录显示&#xff1a;SSH服务器拒绝了密码&#xff0c;请再试一次 这个问题我搜了很多方法&#xff0c;基本数都是让改配置文件。 我在确认物理机和虚拟机互相…

【Windows使用笔记】神舟笔记本的control center

首先&#xff0c;神船大法好。 然后&#xff0c;因为我的船风扇声音有点大啊&#xff0c;在实验室感觉就很吵&#xff0c;但是它的背板温度又不是很高&#xff0c;所以想设置下风扇的启动。 所以需要用到神船自带的control center软件。 长这样。 应该使用热键fnesc就可以调用出…

MIL开发实践(4)——E2v相机参数

目录 前言效果图正文连接串口向串口写入命令举例设置的参数ComBox类型Int类型 总结 前言 这篇文章的主要内容是完成对相机参数这部分的配置。因为这个相机参数这个接口的特殊原因&#xff0c;只能采用串口的形式才能对相机的参数进行设置&#xff0c;所以&#xff0c;需要具备…

机械师怎么打开计算机管理,机械师创物者-R笔记本智能控制中心使用教程

②在官网“驱动下载”页面下选择“MACHENIKE-R”对应的配置驱动,找到“控制中心驱动”选项,点击“立即下载”。 ③ 下载完成后,对zip压缩包进行解压操作,双击文件夹中的“UniwillService.exe”开始安装。 ④ 软件的安装流程十分简单,只需要点击进程中的“install”选项开始…

[基础]tfcenter的安装和启动

文章系列 tfcenter的安装和启动 tfcenter开启端口映射功能 tfcenter开启本地文件功能 tfcenter开启Webdav文件服务 tfcenter开启http代理功能 tfcenter开启socks5代理功能 tfcenter搭建个人服务器 tfcenter支持端口映射、本地文件管理、Webdav文件服务、http代理和socks…

redis简单介绍

&#xff08;一&#xff09;redis简介 what: Redis是一个开源的、基于内存的缓存数据库 Redis&#xff1a;支持每秒十几万此的读/写操作 场景&#xff1a;由于一般的系统任务中通常不会存在高并发的情况&#xff0c;所以这样看起来并没有什么问题&#xff0c;可是一旦涉及大…

Mac端口5000被ControlCe占用问题解决方法

问题 Mac上运行flask应用时提示端口5000已被占用。 查看占用情况&#xff1a; $ lsof -i:5000 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME ControlCe 70052 jiaqi 24u IPv4 0xa620acf2cebbe09f 0t0 TCP *:commplex-main (LISTEN) C…

android 控制中心os,控制中心Control Center--IOS 11

控制中心Control Center--IOS 11 介绍 控制中心Control Center--IOS 11 ?控制中心Control Center--IOS 11便捷操控手机&#xff0c;一键访问相机&#xff0c;闹钟等功能和应用&#xff0c;便捷调控音量等 控制中心Control Center--IOS 11完美适配三星&#xff0c;华为&#xf…

触摸板失效,fn快捷键不显示,神舟control center3.0无法打开等问题重装驱动

神舟电脑 Hasee -- 服务与支持 在上面的网站找到自己电脑型号的驱动&#xff0c;然后找到控制中心或者热键的驱动&#xff0c;我的是控制中心 下载解压好之后进行安装 安装好之后找到这个路径&#xff0c;我是把里面的东西都安装了一遍&#xff0c;安装好后他自动打开是英文的…

EMC ControlCenter 6.1 install update bandle 9 failed

https://community.emc.com/message/553651#553651 问题是&#xff1a; Aleksandr 2011-7-5 上午6:25 I install update bandle 9 on the ControlCenter 6.1 but instal failed with this error: StorageScope Repository Pre-upgrade failed.Please review log: sys password…

Javalin:一个轻量的 Web Framework

说起 Java 语言下的 Web 框架那就非 Spring Framework 不可了&#xff0c;但是今天在和别人在聊天的过程中发现了一个新奇的项目 Javalin。Javalin 是一个轻量的 Web 框架。支持 WebSocket, HTTP2 和异步请求。简单的看了一下官方的说明文档&#xff0c;确实非常轻量&#xff0…

ControlCenter and Dataviewer

Hardware and cable assignment Download: https://sensirion.com/products/sensor-evaluation/control-center/ logging address: “File” --> “Setting” --> “Output Directory” data folder: “File” --> “Open Data Log Folder” Plot the data …

战神 控制中心 controlcenter安装

前言 啊啊啊啊&#xff0c;终于解决问题了&#xff0c;希望对正在看的您有所帮助&#xff01; 首先说下背景&#xff0c;本人使用的是战神Z7-CT7NA&#xff0c;昨天重装了win10的系统&#xff0c;在官网 战神电脑驱动下载 下载对应的电脑驱动&#xff0c;安装了&#xff0c;可…