深度学习编译:MLIR初步

深度学习编译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

MLIR(Multi-Level Intermediate Representation,多级中间表示)是一种用来构建可重用可扩展编译基础设施的新方法。MLIR旨在解决软件碎片化,改进异构硬件的编译,显著减少构建特定领域编译器的成本,并帮助连接现有的编译器。

具体来说,MLIR是通过定义一个通用的中间表示(IR),将在TensorFlow和类似的ML框架中执行高性能机器学习模型所需的基础设施进行统一,包括高性能计算技术应用或强化学习这类搜索算法的集成。MLIR旨在降低开发新硬件的成本,并提高现有TensorFlow用户的可用性。

在这里插入图片描述

MLIR通过一种混合的中间表示,实现在一个统一的架构基础上支持以下多个不同的需求:

  1. 表征数据流图的能力,包括动态形状(dynamic shape),用户可扩展的操作集,TensorFlow变量,等等。
  2. 支持典型的图优化和图变换,例如TensorFlow Grappler。
  3. 可以以一种易于优化的形式来表征ML操作的Kernel。
  4. 具备掌控跨Kernel的高性能计算风格(high-performance-computing-style)循环优化(例如fusion,loop interchange,tiling等polyhedral compilation)的能力,以及变换数据内存排布的能力。
  5. 代码生成“下降lowering”转换,显式的插入DMA,显示的缓存cache管理,内存分块tiling,为适应1D和2D寄存器架构的自动向量化
  6. 表达特定后端操作的能力,比如特定加速器的高层操作。
  7. 在深度学习图上已有的量化和其他图变化。

MLIR 并非万能,不支持底层机器代码生成的算法(比如寄存器分配和指令调度),这些更适合于低层优化器(如llvm),它也不支持用户手写Kernel(不同于CUDA)。MLIR是提供一种框架,使自定义的 DSL(Domain-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,绿色阴影部分是基于 SSA(static 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的模型。整个的编译过程,从源语言生成AST(Abstract 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/532695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入浅出LLVM

深入浅出LLVM 转自:https://www.jianshu.com/p/1367dad95445 什么是LLVM? LLVM项目是模块化、可重用的编译器以及工具链技术的集合。 美国计算机协会 (ACM) 将其2012 年软件系统奖项颁给了LLVM,之前曾经获得此奖项的软件和技术包括:Java、A…

一分钟系列:什么是虚拟内存?

一分钟系列:什么是虚拟内存? 转自:https://mp.weixin.qq.com/s/opMgZrXV-lfgOWrNUMKweg 注:一分钟系列的篇幅都不长,适合吃饭蹲坑、地铁公交上食用~ 内存对于用户来说就是一个字节数组,我们可…

11-Kafka

1 Kafka Kafka是一个分布式流式数据平台,它具有三个关键特性 Message System: Pub-Sub消息系统Availability & Reliability:以容错及持久化的方式存储数据记录流Scalable & Real time 1.1 Kafka架构体系 Kafka系统中存在5个关键组件 Producer…

虚拟内存精粹

虚拟内存精粹 标题:虚拟内存精粹 作者:潘建锋 原文:HTTPS://strikefreedom.top/memory-management–virtual-memory 导言 虚拟内存是当今计算机系统中最重要的抽象概念之一,它的提出是为了更加有效地管理内存并且降低内存出错的概…

深度学习自动编译和优化技术调研

深度学习自动编译和优化技术调研 转自:https://moqi.com.cn/blog/deeplearning/ 作者:墨奇科技全栈开发 在墨奇科技,我们需要将一些包含深度神经网络(DNN)的 AI 算法移植到边缘端的设备, 这些设备往往使用 …

Copy-On-Write COW机制

Copy-On-Write COW机制 转自:https://zhuanlan.zhihu.com/p/48147304 作者:Java3y 前言 只有光头才能变强 在读《Redis设计与实现》关于哈希表扩容的时候,发现这么一段话: 执行BGSAVE命令或者BGREWRITEAOF命令的过程中&#xff0c…

第2章线性表的基本使用及其cpp示例(第二章汇总,线性表都在这里)

2.1线性表的定义和特点 【类型定义: *是n个元素的有限序列 *除了第一个元素没有直接前驱和最后一个没有直接后驱之外,其余的每个元素只有一个直接前驱和直接后驱; (a1,a2…an) 【特征: *有穷性&#xff1…

2.3单链表的基本使用及其cpp示例

2.3线性表的链式表现与实现 2.3.1.1单链表 【特点: *用一组任意的存储单元存储线性表的数据元素 *利用指针实现用不同相邻的存储单元存放逻辑上相邻的元素 *每个元素ai,除存储本身信息外,还存储其直接后继的元素(后一个元素的地址…

TVM:简介

TVM:简介概述 Apache TVM 是一个用于 CPU、GPU 和机器学习加速器的开源机器学习编译器框架。它旨在使机器学习工程师能够在任何硬件后端上高效地优化和运行计算。本教程的目的是通过定义和演示关键概念,引导您了解 TVM 的所有主要功能。新用户应该能够从…

2.3.3单链表的双向链表

2.3.3双向链表 插入、删除 指在前驱和后驱方向都能游历(遍历)的线性链表 双向链表的每个结点有两个指针域 【结构】:prior data next 双链表通常采用带头结点的循环链表形式 可理解为首位相接的数据“圈”,每个结点都可以向前…

nvidia-smi 命令详解

nvidia-smi 命令详解 简介 nvidia-smi - NVIDIA System Management Interface program nvidia smi(也称为NVSMI)为来自 Fermi 和更高体系结构系列的 nvidia Tesla、Quadro、GRID 和 GeForce 设备提供监控和管理功能。GeForce Titan系列设备支持大多数…

2.4一元多项式的表示及相加,含cpp算法

2.4一元多项式的表示及相加 n阶多项式的表示: n阶多项式有n1项 指数按升幂排序 【 优点: 多项式的项数可以动态增长,不存在存储溢出的问题插入,删除方便,不移动元素 【表示: 有两个数据域,一…

TVM:使用Tensor Expression (TE)来处理算子

TVM:使用Tensor Expression (TE)来处理算子 在本教程中,我们将聚焦于在 TVM 中使用张量表达式(TE)来定义张量计算和实现循环优化。TE用纯函数语言描述张量计算(即每个表达式都没有副作用)。当在 TVM 的整体…

4-数据结构-串的学习

4.1串类型的定义 1.串:(或字符串) 串是由多个字符组成的有限序列,记作:S‘c1c2c3…cn’ (n>0) 其中S是串的名字,‘c1c2c3…cn’ 是串值 ci是串中字符 n是串的长度,表示字符的数目 空串&a…

5-数据结构-数组的学习

5.1数组的定义 定义: 由一组类型相同的数据元素构成的有序集合,每个数据元素称为一个数据元素(简称元素),每个元素受n(n>1)个线性关系的约束,每个元素在n个线性关系中的序号i1、…

timm 视觉库中的 create_model 函数详解

timm 视觉库中的 create_model 函数详解 最近一年 Vision Transformer 及其相关改进的工作层出不穷,在他们开源的代码中,大部分都用到了这样一个库:timm。各位炼丹师应该已经想必已经对其无比熟悉了,本文将介绍其中最关键的函数之…

C--数据结构--树的学习

6.2.1二叉树的性质 1.二叉树 性质: 1.若二叉树的层次从1开始,则在二叉树的第i层最多有2^(i-1)个结点 2.深度为k的二叉树最多有2^k -1个结点 (k>1) 3.对任何一颗二叉树,如果其叶结点个数为n0,度为2的非叶结点个数…

C语言—sort函数比较大小的快捷使用--algorithm头文件下

sort函数 一般情况下要将一组数从的大到小排序或从小到大排序&#xff0c;要定义一个新的函数排序。 而我们也可以直接使用在函数下的sort函数&#xff0c;只需加上头文件&#xff1a; #include<algorithm> using namespace std;sort格式&#xff1a;sort(首元素地址&…

AI编译器与传统编译器的联系与区别

AI编译器与传统编译器的区别与联系 总结整理自知乎问题 针对神经网络的编译器和传统编译器的区别和联系是什么&#xff1f;。 文中提到的答主的知乎主页&#xff1a;金雪锋、杨军、蓝色、SunnyCase、贝壳与知了、工藤福尔摩 笔者本人理解 为了不用直接手写机器码&#xff0…

python学习1:注释\变量类型\转换函数\转义字符\运算符

python基础学习 与大多数语言不同&#xff0c;python最具特色的就是使用缩进来表示代码块&#xff0c;不需要使用大括号 {} 。缩进的空格数是可变的&#xff0c;但是同一个代码块的语句必须包含相同的缩进空格数。 &#xff08;一个tab4个空格&#xff09; Python语言中常见的…