湖南佳邦建设有限公司网站,11个免费网站空间,百度热搜广告设计公司,企业网站建设总结深度学习编译MLIR初步
深度模型的推理引擎
目前深度模型的推理引擎按照实现方式大体分为两类#xff1a;解释型推理引擎和编译型推理引擎。
解释型推理引擎
一般包含模型解析器#xff0c;模型解释器#xff0c;模型优化器。 模型解析器负责读取和解析模型文件#xff…深度学习编译MLIR初步
深度模型的推理引擎
目前深度模型的推理引擎按照实现方式大体分为两类解释型推理引擎和编译型推理引擎。
解释型推理引擎
一般包含模型解析器模型解释器模型优化器。 模型解析器负责读取和解析模型文件转换为适用于解释器处理的内存格式 模型优化器负责将原始模型变换为等价的、但具有更快的推理速度的模型 模型解释器分析内存格式的模型并接受模型的输入数据然后根据模型的结构依次执行相应的模型内部的算子最后产生模型的输出。
编译型推理引擎
编译型推理引擎一般包含模型解析器和模型编译器。
模型解析器的作用与解释型推理引擎相同模型编译器负责将模型编译为计算设备CPU、GPU 等可直接处理的机器码并且可能在编译的过程中应用各种优化方法来提高生成的机器码的效率。
编译型推理引擎的优势
由于机器码的模型可以直接被计算设备处理无需额外的解释器的参与其消除了解释器调度的开销。相对于解释型推理引擎由于生成机器码的过程更加靠底层编译器有更多的优化机会以达到更高的执行效率。由于现在业界对于推理引擎的执行速度有了更高的需求编译型推理引擎也逐渐成为高速推理引擎的发展方向。编译型推理引擎有 Apache TVM、oneDNN、PlaidML、TensorFlow XLA、TensorFlow Runtime 等。
中间表示
为了便于优化一般来说推理引擎会把模型转换为中间表示然后对中间表示进行优化和变换最终生成目标模型对于解释型推理引擎或目标机器码对于编译型推理引擎。此外除了深度学习领域在很早以前编程语言领域就引入了中间表示来做优化和变换。而新的编程语言层出不穷因此就出现了各种各样的中间表示不同的推理引擎或者编译器都会有自己的中间表示和优化方案而每种中间表示和优化方案可能都需要从头实现最终可能会导致软件的碎片化和重复的开发工作。
MLIR
听到这个名字的时候下意识觉得这应该是个关于机器学习的中间表达结构毕竟这年头听到ML都会认为是Machine Learning但是MLIR还真不是Machine Learning Intermediate Representation而是Multi-Level Intermediate Representation。
1. 什么是MLIR
MLIRMulti-Level Intermediate Representation多级中间表示是一种用来构建可重用和可扩展编译基础设施的新方法。MLIR旨在解决软件碎片化改进异构硬件的编译显著减少构建特定领域编译器的成本并帮助连接现有的编译器。
具体来说MLIR是通过定义一个通用的中间表示IR将在TensorFlow和类似的ML框架中执行高性能机器学习模型所需的基础设施进行统一包括高性能计算技术应用或强化学习这类搜索算法的集成。MLIR旨在降低开发新硬件的成本并提高现有TensorFlow用户的可用性。 MLIR通过一种混合的中间表示实现在一个统一的架构基础上支持以下多个不同的需求
表征数据流图的能力包括动态形状dynamic shape用户可扩展的操作集TensorFlow变量等等。支持典型的图优化和图变换例如TensorFlow Grappler。可以以一种易于优化的形式来表征ML操作的Kernel。具备掌控跨Kernel的高性能计算风格high-performance-computing-style循环优化例如fusionloop interchangetiling等polyhedral compilation的能力以及变换数据内存排布的能力。代码生成“下降lowering”转换显式的插入DMA显示的缓存cache管理内存分块tiling为适应1D和2D寄存器架构的自动向量化表达特定后端操作的能力比如特定加速器的高层操作。在深度学习图上已有的量化和其他图变化。
MLIR 并非万能不支持底层机器代码生成的算法比如寄存器分配和指令调度这些更适合于低层优化器如llvm它也不支持用户手写Kernel不同于CUDA。MLIR是提供一种框架使自定义的 DSLDomain-Specific Language领域专用语言 表达可以融入到一个统一的生态。
2. MLIR的作用
虽然 MLIR 中的 ML 不是Machine Learning但是Machine Learning确实是是MLIR的一个重要应用领域。我们接下来主要看一下在机器学习领域MLIR可以做哪些事情。在了解MLIR是怎么工作之前我先得弄明白这个IR在解决什么问题。
说到机器学习我们就用TensorFlow这个框架来举例。我们知道TensorFlow是使用数据流图作为数据结构来进行各种数值计算要让这些计算运行在硬件上我们需要一个TensorFlow的编译生态系统 如图中所示TensorFlow图 能够以多种不同的方式运行包括
将其发送至调用手写运算内核的 TensorFlow 执行器将图转化为 XLA 高级优化器 (XLA HLO) 表示反之这种表示亦可调用适合 CPU 或 GPU 的 LLVM 编辑器或者继续使用适合 TPU 的 XLA。或者将二者结合将图转化为 TensorRT、nGraph 或另一种适合特定硬件指令集的编译器格式将图转化为 TensorFlow Lite 格式然后在 TensorFlow Lite 运行时内部执行此图或者通过 Android 神经网络 API (NNAPI) 或相关技术将其进一步转化以在 GPU 或 DSP 上运行
此外我们有时甚至会采用更复杂的途径包括在每层中执行多轮优化。例如Grappler 框架现在便能优化 TensorFlow 中的张量布局和运算。
通常来说整个编译流程先将TensorFlow的图转化为XLA HLO即一种类似高级语言的图的中间表达形式可以基于此进行一些 High-Level 的优化。接着将XLA HLO翻译为LLVM IR使用LLVM编译到各种硬件的汇编语言从而运行在硬件上进行数值计算。
下图的蓝色阴影部分是 基于图的IR绿色阴影部分是基于 SSAstatic single-assignment静态单一赋值 的IR然而这样的编译方式的缺点在于构建这样的编译系统的开销比较大每一层的设计实现会有重复部分同一个层次的IR彼此之间虽然相似但是存在天生的“生殖隔离”升级优化缺乏迁移性即改变优化一个模块并不能惠及到同层次的其他模块。因此目前存在的问题就在于各种IR之间转换的效率和可迁移性不高。 对于上述问题MLIR希望为各种DSL提供一种中间表达形式将他们集成为一套生态系统使用一种一致性强的方式编译到特定硬件平台的汇编语言上。利用这样的形式MLIR就可以利用它模块化、可扩展的特点来解决IR之间相互配合的问题。 到此为止我们大致知道了MLIR的诞生是为了解决什么问题。目前它对我来说还是一个黑盒子下面的工作就是要去看看MLIR内部究竟是一个什么样的结构看看它是怎么把各层IR整合到一起又是如何实现扩展功能的。
3. MLIR中的 “方言”dialect
为什么要有方言
之前我们说到当前的编译结构的问题在于各种IR之间转换的效率和可迁移性不高。MLIR试图使用一种一致性强的方式为各种DSL提供一种中间表达形式将他们集成为一套生态系统编译到特定硬件平台的汇编语言上。这样的目标是通过什么手段实现的呢
从源程序到目标程序要经过一系列的抽象以及分析通过Lowering Pass来实现从一个IR到另一个IR的转换这样的过程中会存在有些操作重复实现的情况也就导致了转换效率低的问题。
这就好比IR们组成一个流水线要合起伙来干一个大买卖但是互相配合不默契谁也明白不了对方究竟干了啥为了保险起见每个IR拿到上一个IR的产品之后只能多干点活保证不出错这样一来效率自然就低了。MLIR面对这种IR群雄割据的现状打算一统天下打天下容易守天下难呀不让我们用各种IR了你倒是给我们一条活路呀怎么才能让源语言变成汇编语言然后跑在机器上呀于是统一IR的第一步就是要统一“语言”各个IR原来配合不默契谁也理解不了谁就是因为“语言”不通没法用统一的“语言”指挥流水线干活。MLIR看准时机拿出了自己的法宝Dialects让各个IR学习Dialects这个“语言”这样一来不光能指挥流水线高效干活了还能随意扩展更改分工从此IR们就可以完美地分工协作。
为区分不同的硬件与软件受众MLIR 提供 “方言”其中包括
TensorFlow IR代表 TensorFlow 图中可能存在的一切XLA HLO IR旨在利用 XLA 的编译功能输出到 TPU 等实验性仿射方言侧重于多面表示与优化LLVM IR与 LLVM 自我表示之间存在 1:1 映射可使 MLIR 通过 LLVM 发出 GPU 与 CPU 代码TensorFlow Lite将会转换以在移动平台上运行代码
每种方言均由一组存在不变性的已定义操作组成如“这是一个二进制运算符输入与输出拥有相同类型。”
将方言添加至 MLIR
MLIR 没有众所周知的固定或内置的操作列表无 “内联函数”。方言可完全定义自定义类型即 MLIR 如何对 LLVM IR 类型系统拥有一流汇总、域抽象对量化类型等经机器学习 (ML) 优化的加速器有着重要意义乃至未来的 Swift 或 Clang 类型系统围绕 Swift 或 Clang 声明节点而构建进行建模。
如果我们想要连接新的低级编译器则需要创建新方言以及 TensorFlow 图方言与我们的方言之间的降阶。如此一来硬件及编译器制造商便可畅通无阻。我们甚至可以在同一个模型中定位不同级别的方言高级优化器将保留 IR 中不熟悉的部分并等待较低级别的优化器来处理此类部分。
对于编译器研究者和框架制造者则可以借助 MLIR 在每个级别进行转换甚至是在 IR 中定义自己的操作和抽象从而针对试图解决的问题领域构建最佳模型。由此看来MLIR 比 LLVM 更像是纯编译器基础设施。
虽然 MLIR 充当 ML 的编译器但我们也看到MLIR 同样支持在编译器内部使用机器学习技术这一点尤为重要因为在进行扩展时开发数字库的工程师无法跟上 ML 模型或硬件的多样化速度。MLIR 的扩展性有助于探索代码降阶策略并在抽象之间执行逐步降阶。
dialect是如何工作的
dialects是将所有的IR放在了同一个命名空间中分别对每个IR定义对应的产生式以及绑定相应的操作从而生成一个MLIR的模型。整个的编译过程从源语言生成ASTAbstract Syntax Tree抽象语法树借助Dialects遍历AST产生MLIR的表达式此处可为多层IR通过Lowering Pass依次进行分析最后经过MLIR分析器生成目标语言。 这里只是简单介绍一下MLIR中dialect的工作机制参考知乎法斯特豪斯的理解之后会更加详细的进行介绍并增加实例如有错误欢迎讨论。
Ref
https://zhuanlan.zhihu.com/p/101879367
https://zhuanlan.zhihu.com/p/102212806
https://www.sohu.com/a/307133340_670669
https://blog.csdn.net/wujianing_110117/article/details/119312999