【论文阅读】The Deep Learning Compiler: A Comprehensive Survey

news2024/11/14 21:38:11

论文来源:Li M , Liu Y , Liu X ,et al.The Deep Learning Compiler: A Comprehensive Survey[J]. 2020.DOI:10.1109/TPDS.2020.3030548.

这是一篇关于深度学习编译器的综述类文章。

什么是深度学习编译器

深度学习(Deep Learning)编译器将深度学习框架描述的模型在各种硬件平台上生成有效的代码实现,其完成的模型定义到特定代码实现的转换将针对模型规范和硬件体系结构高度优化。具体来说,它们结合了面向深度学习的优化,例如层融合和操作符融合,实现高效的代码生成。

此外,现有的编译器还采用了来自通用编译器(例如LLVM)的成熟工具链,对各种硬件体系结构提供了更好的可移植性。

简而言之,深度学习编译器通过对深度学习模型和计算图的优化,以及对硬件资源的充分利用,提高了深度学习模型的性能和效率。这使得深度学习模型在边缘设备和嵌入式系统上能够更好地运行。

深度学习编译器的基本架构

与传统编译器类似,深度学习编译器也采用分层设计,其通用设计架构主要包括编译器前端和编译器后端,其中IR(中间语言)分布在前端和后端,它是程序的抽象,用于程序优化。

深度学习模型在深度学习编译器中被转换为多级IR,其中高阶IR驻留在前端,低阶IR驻留在后端。基于高阶IR,编译器前端负责与硬件无关的转换和优化。基于低阶IR,编译器后端负责特定于硬件的优化、代码生成和编译。

高阶IR,也称为graph IR,表示计算和控制流,与硬件无关。高阶IR的设计挑战是计算和控制流的抽象能力,能够捕获和表达不同的DL模型。高阶IR的目标是建立控制流和op(算子)与数据之间的依赖关系,以及为图级优化提供接口。它还包含用于编译的丰富语义信息,并为定制算子提供可扩展性。

低阶IR是为特定于硬件的优化和针对不同硬件目标的代码生成而设计的。因此,低阶IR应该足够细粒度,以反映硬件特征并表示特定于硬件的优化。

前端将现有的Deep Learning框架中的模型作为输入,然后将该模型转换为计算图表示(例如,graph IR)。前端需要实现多种格式转换,以支持不同框架下的多种格式。计算图优化结合了通用编译器的优化技术和Deep Learning特定优化技术,减少了graph IR的冗余,提高了图graph IR的效率。这样的优化可以分为:

  1. node节点级(例如,nop消除和零维张量消除)

  2. block块级(代数简化、算子融合、op下降)

  3. 数据流层(例如CSE、DCE、静态内存规划和布局转换)。

前端完成后,生成优化的计算图并传递给后端,后端将高阶IR转换为低阶IR并执行特定于硬件的优化。一方面,它可以直接将高阶IR转换为第三方工具链,如LLVM IR,以利用现有的基础设施进行通用优化和代码生成。另一方面,它可以利用DL模型和硬件特性的先验知识,通过定制的编译通道,实现更高效的代码生成。通常应用的特定于硬件的优化包括硬件内在映射、内存分配和获取、内存延迟隐藏、并行化以及面向循环的优化。

前端优化

在构建计算图之后,前端应用图级优化。许多优化更容易在图级识别和执行,因为图提供了计算的全局视图。这些优化只应用于计算图,而不是后端实现。因此,它们是独立于硬件的,可以应用于各种后端目标。

前端优化通常由passes定义,可以通过遍历计算图的节点并执行图转换来应用。前端提供了如下方法:

  1. 从计算图中捕获特定的特征;

  2. 重写图以进行优化。

除了预定义的passes,开发人员还可以在前端定义定制的passes。一旦一个Deep Learning模型被导入并转换为一个计算图,大多数DL编译器可以确定每个操作的输入张量和输出张量的形状。

节点级优化

计算图的节点足够粗粒度,可以在单个节点内进行优化。节点级优化包括:

  1. 节点消除(消除不必要的节点)

  2. 节点替换(用其他低成本节点替换节点)

在通用编译器中,Nop消除删除占用少量空间但不指定操作的no-op指令;在DL编译器中,Nop消除负责消除缺少足够输入的操作。例如,只有一个输入张量的和节点可以被消除,填充宽度为零的填充节点可以被消除。

块级优化

代数简化

代数简化优化包括:

  1. 代数识别

  2. 强度约简,我们可以用更便宜的算子取代更昂贵的算子

  3. 常数折叠,用它可以用它们的值替换常量表达式。

算子融合

算子融合是DL编译器不可缺少的优化方法。它能够更好地共享计算,消除中间分配,通过结合loop nests进一步优化,并减少launch和同步开销。

算子Sinking

算子Sinking这种优化将转置等操作置于批处理归一化、ReLU、sigmoid和channel shuffle等操作之下。

通过算子Sinking这种优化,许多相似的操作彼此之间移动得更近,为代数简化创造了更多的机会。

数据流级优化

通用子表达式消除(CSE)

如果表达式E的值之前已经计算过,并且E的值在之前的计算之后没有改变,那么它就是通用子表达式。

在这种情况下,E的值只计算一次,并且可以使用已经计算出的E的值来避免在其他地方重新计算。深度学习编译器在整个计算图中搜索公共子表达式,并用之前的计算结果替换下面的公共子表达式。

死代码消除(DCE)

如果一组代码的计算结果或副作用没有被使用,那么它就是死代码。

DCE优化会删除死代码。死代码通常不是由程序员引起的,而是由其他图优化引起的。因此DCE和CSE是在其他图优化之后应用的。

静态内存规划

使用静态内存规划优化以尽可能重用内存缓冲区,通常有两种方法:

  1. in-place内存共享

  2. 标准内存共享

in-place内存共享使用相同的内存作为操作的输入和输出,只在计算之前分配一个内存副本。标准内存共享重用以前操作的内存,而不重叠。静态内存规划是离线完成的,这允许应用更复杂的规划算法。

布局转变

布局转换试图找到最佳的数据布局来存储张量到计算图中,然后将布局转换节点插入到图中。

注意,这里不执行实际的转换,而是在编译器后端计算计算图时执行转换。事实上,相同操作在不同的数据布局中的性能是不同的,最佳布局在不同的硬件上也是不同的。

后端优化

特定于硬件的优化

特定于硬件的优化也称为目标相关优化,用于获得针对特定硬件的高性能代码。应用后端优化的一种方法是将低层IR转换为LLVM IR,利用LLVM基础设施生成优化的CPU/GPU代码。另一种方法是使用DL领域知识设计定制优化,更有效地利用目标硬件。

以下有五种在现有DL编译器中广泛采用的方法:

硬件固有的映射

硬件内在映射可以将一定的一组低层IR指令转换为已经在硬件上高度优化的内核。在TVM中,硬件本征映射采用可扩展张量化方法实现,可声明硬件本征的行为和本征映射的降低规则。这种方法使编译器后端能够将硬件实现和高度优化的手工微内核应用到特定的操作模式中,从而获得显著的性能提升。

内存分配和获取

内存分配是代码生成中的另一个挑战,特别是对于gpu和定制加速器。例如,GPU主要包含共享内存空间(内存大小有限,访问时延较低)和本地内存空间(容量大,访问时延较高)。这样的内存层次结构需要有效的内存分配和获取技术来改善数据局部性。为了实现这一优化,TVM引入了内存作用域的调度概念。内存作用域调度原语可以将计算阶段标记为共享的或线程本地的。对于标记为共享的计算阶段,TVM生成具有共享内存分配和协同数据获取的代码,并在适当的代码位置插入内存屏障以保证正确性。

内存延迟隐藏

通过对执行管道重新排序,内存延迟隐藏也是在后端使用的一项重要技术。由于大多数DL编译器支持CPU和GPU上的并行化,内存延迟隐藏可以自然地通过硬件实现(例如,GPU上的扭曲上下文切换)。但是对于具有解耦访问库(DAE)体系结构的TPU类加速器,后端需要执行调度和细粒度同步以获得正确和高效的代码。为了获得更好的性能和减轻编程负担,TVM引入了虚拟线程调度原语,允许用户在虚拟多线程架构上指定数据并行度。然后,TVM通过插入必要的内存屏障,并将来自这些线程的操作穿插到单个指令流中,从而降低了这些实际上并行的线程,这形成了每个线程更好的执行管道,以隐藏内存访问延迟。

面向循环优化

面向循环的优化也应用于后端,为目标硬件生成高效的代码。由于Halide和LLVM已经集成了这样的优化技术,一些DL编译器在后端利用了Halide和LLVM。面向循环优化中应用的关键技术包括循环融合、滑动窗口、平铺、循环重排序和循环展开。

并行化

由于现代处理器通常支持多线程和SIMD并行性,编译器后端需要利用并行性来最大化硬件利用率,以实现高性能。

Halide使用一个叫做parallel的调度原语来指定线程级别并行化的循环的并行化维度,并通过将标记为parallel的循环维度与块和线程的注释进行映射来支持GPU并行化。它将一个大小为n的循环替换为一个宽为n的向量语句,该向量语句可以通过硬件内在映射映射到特定于硬件的SIMD操作码。

Stripe发展了一种多面体模型的变体,称为嵌套多面体模型,该模型引入了并行多面体块作为迭代的基本执行元素。在此扩展之后,一个嵌套的多面体模型可以检测平铺和跨步级别之间的层次并行性。

自动调优

由于在特定于硬件的优化中参数调优有巨大的搜索空间,因此有必要利用自动调优来确定最佳参数配置。在A Comprehensive Survey[4]这篇论文中研究的DL编译器中,TVM、TC和XLA支持自动调优。通常,自动调优实现包括Parameterization(参数化)、代价模型、搜索技术和加速四个关键部分。

Parameterization(参数化)

数据参数描述数据的规格,如输入的形状。目标参数描述在优化调度和代码生成期间要考虑的特定于硬件的特征和约束。例如,对于GPU目标,需要指定共享内存和寄存器大小等硬件参数。

优化选项包括优化调度和相应的参数,如面向循环的优化和瓷砖大小。在TVM中,既考虑了预定义调度,也考虑了自定义调度,还考虑了参数。

代价模型

自动调优中不同代价模型的比较如下:

  1. 黑箱模型:该模型只考虑最终的执行时间,而不考虑编译任务的特征。建立黑盒模型很容易,但是如果没有任务特性的指导,很容易导致更高的开销和更少的最优解。TC采用了这种模式。

  2. 基于ML的代价模型:基于ml的成本模型是一种使用机器学习方法预测性能的统计方法。它使模型能够随着新配置的探索而更新,这有助于实现更高的预测精度。TVM和XLA采用这种模型,分别是梯度树提升模型(GBDT)和前馈神经网络。

  3. 预定义代价模型:基于预定义代价模型的方法,期望根据编译任务的特点建立一个完美的模型,能够评估任务的整体性能。与基于ML的模型相比,预定义模型在应用时产生的计算开销更少,但需要在每个新的DL模型和硬件上重新构建模型,需要大量的工程工作。

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

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

相关文章

getInputStream has already been called for this request 问题记录

问题背景 HttpServletRequest.getReader() HttpServletRequest.getInputStream() 不能在过滤器中读取一次二进制流(字符流),又在另外一个Servlet中读取一次,即一个InputSteam(BufferedReader)对象在被读取完成后,将无…

FPGA XDMA 中断模式实现 PCIE3.0 AD7606采集 提供2套工程源码和QT上位机源码

目录 1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案AD7606数据采集和缓存XDMA简介XDMA中断模式QT上位机及其源码 5、vivado工程1--BRAM缓存6、vivado工程2--DDR4缓存7、上板调试验证8、福利:工程代码的获取 1、前言 PCIE(PCI Express&am…

全方位支持图文和音视频、100+增强功能,Facebook开源数据增强库AugLy

Facebook 近日开源了数据增强库 AugLy,包含四个子库,每个子库对应不同的模态,每个库遵循相同的接口。支持四种模态:文本、图像、音频和视频。 最近,Facebook 开源了一个新的 Python 库——AugLy,该库旨在帮…

Error: unknown flag: --export 【k8s,kubernets报错】

报错情况如下: [rootk8smaster ~]# kubectl get deploy nginx -oyaml --export > my2.yaml Error: unknown flag: --export See kubectl get --help for usage.原因: --export在所使用的版本中已被移除 解决:去除--export即可&#xff0c…

基于Javaweb实现ATM机系统开发实战(十五)退卡和转账跳转实现

首先创建一个servlet接受和处理请求: package com.atm.servlet;import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException;//用户退出 WebServlet("/logout") public class ExitServlet ex…

14、php面向对象3(final、显示调用父类构造方法、static静态变量与方法)

1、如果父类中的方法被声明为 final&#xff0c;则子类无法覆盖该方法。如果一个类被声明为 final&#xff0c;则不能被继承。 <?php class BaseClass{public function test(){echo "BaseClass::test() called".PHP_EOL;}final public function moreTesting(){e…

使用CRM进行数据分析的四大好处

使用CRM数据分析系统够帮助企业更好地了解客户需求和行为习惯&#xff0c;提供个性化的服务&#xff0c;从而提高客户满意度和忠诚度。使用CRM数据分析系统可以为企业带来一些好处&#xff0c;包括提高客户洞察力、加强营销策略、提高运营效率等。 1.提高客户洞察力&#xff1a…

【C++ 重要知识点总结】进制与编码

1 进位计数 数制 2进制----字面量0b8进制----字面量010进制—无16进制0x-字面量0x 数制转化 r进制数转化成十进制 I a n − 1 r n − 1 ⋯ a 0 r 0 I a_{n-1}\times r^{n-1} \cdots a_0 \times r^0 Ian−1​rn−1⋯a0​r0十进制整数转化r进制数——除r取余法 I r…

日志系统:一条SQL更新语句是如何执行的

知识粗粮 为什么mysql 8 把缓存给取消了&#xff1f;&#xff08;在这里我不咋说&#xff0c;很简单&#xff0c;自己去百度&#xff09; mysql 可以回复到半个月内的任意一秒的状态 sql的执行链路&#xff08;8把查询缓存彻底给搞掉了呜呜呜&#xff09; 进入正题 下面我们从…

MyBatis-Flex 是什么(一个优雅的MyBatis增强框架)

直接去看官网吧&#xff1a;MyBatis-Flex - MyBatis-Flex 官方网站 MyBatis-Flex 是一个优雅的 MyBatis 增强框架&#xff0c;它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用 Mybaits-Flex 链接任何数据库&#xff0c;其内置的 QueryWrapper^亮点 帮助我们极大…

集装箱装卸作业相关的知识-Part1

1.角件 Corner Fitting of Container or called Corner Casting. there are eigth of it of one container. 国家标准|GB/T 1835-2006https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcnoD35857F2200FA115CAA217A114F5EF12 中国的国标&#xff1a;GB/T 1835-2006《系列1集…

基于Java+SpringBoot+vue前后端分离网上租赁系统设计实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

可维护性测试

目录 什么是可维护性测试&#xff1f; 如何衡量应用程序的可维护性&#xff1f; 参考资料 如何进行可维护性测试&#xff1f; 可维护性测试最佳实践 易分析性 内部可分析性指标 外部可分析性指标 可变更性&#xff08;易修改性 Changeability | Modifiability&#xf…

pnpm的安装与使用

pnpm使用 官网&#xff1a; https://www.pnpm.cn/installation 简介 1、概念 performant npm &#xff0c;意味“高性能的 npm”。pnpm由npm/yarn衍生而来&#xff0c;解决了npm/yarn内部潜在的bug&#xff0c;极大的优化了性能&#xff0c;扩展了使用场景。被誉为“最先进的包…

五分钟理解Linux磁盘逻辑卷管理LVM

LVM概念 LVM&#xff08;Logical Volume Manager&#xff0c;逻辑卷管理&#xff09;是Linux环境下对磁盘分区进行管理的一种机制。LVM的工作原理其实很简单&#xff0c;它就是通过将底层的物理硬盘抽象的封装起来&#xff0c;然后以逻辑卷的方式呈现给上层应用。在传统的磁盘…

【iOS】iOS持久化

1 持久化目的 快速展示&#xff0c;提升体验 已经加载过的数据&#xff0c;用户下次查看时&#xff0c;不需要再次从网络&#xff08;磁盘&#xff09;加载&#xff0c;直接展示给用户 节省用户流量&#xff08;节省服务器资源&#xff09; 对于较大的资源数据进行缓存&#x…

容器管理工具 portainer可视化面板 的安装及使用

大家好&#xff0c;我是早九晚十二&#xff0c;目前是做运维相关的工作。写博客是为了积累&#xff0c;希望大家一起进步&#xff01; 我的主页&#xff1a;早九晚十二 什么是portainer Portainer是一款轻量级的Docker图形化管理的方案&#xff0c;相比k8s和k3s&#xff0c;只需…

Dev C++下载安装

1、下载 下载地址&#xff1a;Dev-C download | SourceForge.nethttps://sourceforge.net/projects/orwelldevcpp/ 点击“Download”下载 新建文件夹用于安装 2、安装 双击exe文件执行安装程序&#xff0c;选择“English”&#xff08;我没看到普通话&#xff09; 选择“I …

简单的语音广播功能方案

方案介绍&#xff1a; 1&#xff09;前端可以复用如下播放器的方案 &#xff08;或自行实现&#xff09; 其中&#xff0c;rtp封装过程中&#xff0c;额外增加了2字节的长度信息&#xff0c;后端服务接收之后&#xff0c;做好校验之后&#xff0c;需要剔除2个字节的数据头 2&a…

.Net Core依赖注入

.Net Core依赖注入 往期文章&#xff1a; .ner Core实现接口限流.net Core程序发布到IIS(Window Server 2019) 文章目录 .Net Core依赖注入前言一、ICO 和DI和DLICO [控制反转]DI [依赖注入]DL [依赖查找] 二、.net Core 中的依赖注入【Autofac】瞬时模式作用域模式单例模式尝…