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

蓝桥杯真题训练 2019.2题

2019第二题 标题:年号字串(本题总分:5 分) 小明用字母 A 对应数字 1,B 对应 2,以此类推,用 Z 对应 26。对于 27 以上的数字,小明用两位或更长位的字符串来对应,例如 AA…

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

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

蓝桥杯真题训练 2019.3题

标题:数列求值 (本题总分:10 分)### 给定数列 1, 1, 1, 3, 5, 9, 17, …,从第 4 项开始,每项都是前 3 项的和。求 第 20190324 项的最后 4 位数字。 【答案提交】 这是一道结果填空的题,你只需…

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 导言 虚拟内存是当今计算机系统中最重要的抽象概念之一,它的提出是为了更加有效地管理内存并且降低内存出错的概…

蓝桥杯真题训练 2019.4题

标题: 数的分解(本题总分:10 分) 【问题描述】 把 2019 分解成 3 个各不相同的正整数之和,并且要求每个正整数都不包 含数字 2 和 4,一共有多少种不同的分解方法? 注意交换 3 个整数的顺序被视…

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

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

三元组数据处理系统

include<stdio.h> include<stdlib.h> define OK 1 define ERROR 0 define OVERFLOW -2 typedef int Status; typedef float ElemType; typedef ElemType *Triplet; // 声明Triplet为ElemType指针类型 //三元组的初始化 Status initTriplet(Triplet &T, E…

Copy-On-Write COW机制

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

实验报告:抽象数据类型的表现和实现

实验报告&#xff1a;抽象数据类型的表现和实现 实验内容 基本要求&#xff1a; 设计实现抽象数据类型“三元组”&#xff0c;要求动态分配内存。每个三元组由任意三个实数的序列构成&#xff0c;基本操作包括&#xff1a;创建一个三元组&#xff0c;取三元组的任意一个分量&…

关于x86、x86_64/x64、amd64和arm64/aarch64

关于x86、x86_64/x64、amd64和arm64/aarch64 转自&#xff1a;https://www.jianshu.com/p/2753c45af9bf 为什么叫x86和x86_64和AMD64? 为什么大家叫x86为32位系统&#xff1f; 为什么软件版本会注明 for amd64版本&#xff0c;不是intel64呢&#xff1f; x86是指intel的开…

实验报告: 线性表的基本操作及应用

实验报告&#xff1a; 线性表的基本操作及应用 实验内容 基本要求&#xff1a; &#xff08;1&#xff09;实现单链表的创建&#xff1b;&#xff08;2&#xff09;实现单链表的插入&#xff1b;&#xff08;3&#xff09;实现单链表的删除 &#xff08;4&#xff09;实现单链…

TVM:源码编译安装

TVM&#xff1a;Linux源码编译安装 笔者环境&#xff1a; OS&#xff1a;Ubuntu 18.04 CMake&#xff1a;3.10.2 gcc&#xff1a;7.5.0 cuda&#xff1a;11.1 编译安装过程总览 本文将简介 tvm 的编译安装过程&#xff0c;包含两个步骤&#xff1a; 通过C代码构建共享库设置相…

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

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

TVM:通过Python接口(AutoTVM)来编译和优化模型

TVM&#xff1a;通过Python接口&#xff08;AutoTVM&#xff09;来编译和优化模型 上次我们已经介绍了如何从源码编译安装 tvm&#xff0c;本文我们将介绍在本机中使用 tvm Python 接口来编译优化模型的一个demo。 TVM 是一个深度学习编译器框架&#xff0c;有许多不同的模块…

TVM:在树莓派上部署预训练的模型

TVM&#xff1a;在树莓派上部署预训练的模型 之前我们已经介绍如何通过Python接口&#xff08;AutoTVM&#xff09;来编译和优化模型。本文将介绍如何在远程&#xff08;如本例中的树莓派&#xff09;上部署预训练的模型。 在设备上构建 TVM Runtime 首先我们需要再远程设备…

2.2线性表的顺序表

2.2.1线性表的顺序表示和实现------顺序映像 【顺序存储】在【查找时】的时间复杂度为【O(1)】&#xff0c;因为它的地址是连续的&#xff0c;只要知道首元素的地址&#xff0c;根据下标可以很快找到指定位置的元素 【插入和删除】操作由于可能要在插入前或删除后对元素进行移…

TVM:交叉编译和RPC

TVM&#xff1a;交叉编译和RPC 之前我们介绍了 TVM 的安装、本机demo和树莓派远程demo。本文将介绍了在 TVM 中使用 RPC 进行交叉编译和远程设备执行。 通过交叉编译和 RPC&#xff0c;我们可以在本地机器上编译程序&#xff0c;然后在远程设备上运行它。 当远程设备资源有限…

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

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