动态尺寸模型优化实践之Shape Constraint IR Part I
简介: 在本系列分享中我们将介绍BladeDISC在动态shape语义下做性能优化的一些实践和思考。本次分享的是我们最近开展的有关shape constraint IR的工作,Part I 中我们将介绍问题的背景,面临的主要挑战和以及我们做shape constraint IR的动机。
在本系列分享中我们将介绍BladeDISC在动态shape语义下做性能优化的一些实践和思考。本次分享的是我们最近开展的有关shape constraint IR的工作,鉴于篇幅较长,为了提升阅读体验,我们将分享拆分为两个部分:
- Part I 中我们将介绍问题的背景,面临的主要挑战和以及我们做shape constraint IR的动机;
- Part II 中我们将介绍shape constraint IR的设计,实现以及一些初步的实验结果;
本篇是关于Part I的介绍,Part II的介绍将后续发出。
背景和挑战
主流的AI模型在部署时一般都具备不同程度的动态shape问题,比如输入图片尺寸,batch size 或者序列长度的变化等。与静态shape语义下做优化相比,在动态shape语义下做优化由于缺少具体的shape信息往往具有更大的难度,主要体现在以下几个方面:
挑战1:优化目标的转变。在静态shape下,我们的优化目标是希望在给定的shape下,尽可能逼近理论上限的速度,针对不同的shape可以使用不同的优化手段,而在动态shape语义下,我们优化目标是希望使用一套方法提升在整个shape分布上的平均性能,更强调的是优化方法的跨shape可迁移性和稳定性。因此很多在静态shape下常用的优化,比如profling驱动的策略,将不再简单可用。
挑战2:更少的有效信息。优化AI模型时很多常见的手段都把一些shape关系的断言是否成立作为优化触发的前置条件。比如在计算图化简时消除冗余的broadcast op,需要依赖于判断输入和输出是否具有相同的shape。在静态shape语义下,判断常量shape是否相等是显然的,而动态shape语义下,判断symbolic shape相等则困难的多,而一旦我们无法有效判断这些前置的shape关系断言是否成立,后续优化都无法进行,因而丢失很多优化机会,拉大与静态shape情况下性能的差异。
挑战3:更复杂的计算图。在动态shape语义下,由于shape不再是编译(或者优化)期间的常量,整个计算图中混杂着计算shape的IR以及计算data的IR,使得整个计算图的分析和优化都变得更复杂,同时也会引入更多shape相关计算的开销。
下图中展示了一个支持numpy语义implicit broadcast (IB)的Add OP的例子以说明计算图变复杂的具体过程。在IB语义下,Add OP在运行时会根据输入shape之间的关系,隐式的插入broadcast运算,所以下图左侧中展示的三种可能输入都是合法的。在静态shape语义下我们很容易在编译期就区分开实际是那种情况,故而在编译时只需要对一种具体情况进行处理,而在动态shape语义下,由于编译期间无法进行区分,我们需要确保编译的结果在三种情况下都可以工作,因而会在计算图中引入显示的shape 计算的IR以及broadcast操作(如下图右侧所示)。在这个例子中上层框架中一个普通的Add OP在动态shape语义下,也会被展开成一个复杂的子图。
也正因为上述的这些挑战,目前成熟的优化工具(如TensorRT,XLA/TVM)对于动态shape支持都还比较有限。BladeDISC是阿里云计算平台PAI团队自研的一款原生支持动态shape的AI编译器。在过往一段时间我们开发BladeDISC优化动态shape模型的过程中,我们发现尽管不知道shape的具体的数值,但是通过充分发掘和利用Tensor的shape之间的结构化关系或者Tensor shape自身的分布特点,可以有效的解决上述挑战。在这里我们把Tensor的shape之间的结构化关系或者Tensor shape自身的分布统称为shape constraint。更进一步的,我们发现通过将shape constraint作为第一等公民引入到IR中,可以最大化的发挥shape constraint的效能。本文中我们将介绍BladeDISC中shape constraint IR的定义以及如何利用它来辅助完成一系列动态shape语意下的优化以解决上述挑战,缩小与静态shape之间的性能差异。
动机
为什么选择shape constraint?
在上一章节中我们分析了在动态shape语义下给做优化所带来的一系列挑战。我们发现使用shape constraint可以有效的解决这些优化上面临的困难。以下我们将分别介绍使用shape constraint如何有效解决上述的三个挑战。
应对挑战1:跨shape可迁移性
在具体分析之前,我们先看shape constraint在本文中的定义。假设一个tensor的rank是N,则该tensor的shape可以记为(d0, d1, ... dN-1)
,其中di
表示的是该tensor在第i
个轴上所具有的大小,也记为第i
个轴的dimension size
。文本中讨论的shape constraint可以分为以下两类:
- shape结构化约束。该类约束描述的是dimension size之间的相关关系,比如:
- dimension size相等关系:某一个tensor的
di
与另外一个tensor的dj
具有相同的大小,或者同一个tensor的di
与dj
具有相同的大小; - tensor元素个数相等:即一个tensor和另外一个tensor具有相同数量的元素;
- dimension size乘积相等关系:比如
reshape([a, b, c, d]) -> [a*b, c*d]
- shape分布约束。该类约束描述的是某个或某几个dimension size的(联合)分布,比如:
di % 4 = 0
,di != 0
,di * dj=10
;- likely values: 即描述某个dimension size更大概率可能取到的值;
- value range:即描述某个dimension size可能的取值区间;
由上述定义本身我们可以立刻得到一个结论:由于无论是shape结构化约束还是分布约束都不依赖于具体的shape值,因此基于shape constraint而构建的优化策略天然具备跨shape可迁移性。
应对挑战2:shape关系断言分析
很多重要的优化都将一些shape关系的断言是否成立作为优化触发的前置条件,比如:
- 计算图化简。比如上文提到的消除冗余的broadcast节点的例子。
- 计算图layout全局优化。计算密集型算子的性能和其输入输出的数据排布(layout)有很强的关系,一个更合适的layout往往具有更好的性能。而一般最优的layout是随着shape而变化的,导致在动态shape语意下无法静态确定最优的layout;这里一种优化策略是:将shape兼容的计算密集算子分到一组,只需要在组间插入layout转化的算子,而组内由于可以确认使用同一种layout而不必再插入layout转化的算子,从而提升性能;这里shape兼容的断言是优化触发的前置条件。
- fusion决策。在做算子融合时并不是越多越好,只有将shape兼容的算子进行融合才会取得比较好的效果,同样里shape兼容的断言的判定是做算子融合的前置条件。
在动态shape语义下,由于不知道shape具体的值,symbolic shape关系的断言的分析往往是困难的。symbolic shape关系的断言可以看成是symbolic dimension size间的关系断言的逻辑关系表达式,因而问题可以转换成对于symbolic dimension size间的关系断言的判定。而由前述shape constraint定义可知,symbolic dimension size间的关系断言本身是shape constraint一个实例。在这里我们把判定symbolic dimension size间的关系断言是否成立的这个问题转换成该断言是否是已知原子shape constraint的组合。这里“原子”的定义是不能够通过其他shape constraint 的实例的组合得到。举个例子,假设我们需要判定tensor A: tensor
是否比tensor B: tensor
具有更多的元素个数,这个问题经过转换过之后可以变成dimension size关系a > b
是否成立。
在完成上述问题的转换之后,目前剩下的未解决的问题是:如何获得已知结果的原子shape constraint。具体来说有以下几种方式:
- 由用户提供或在JIT编译期间自动捕获。比如用户可以提供关于模型输入shape range,JIT编译期间可以将捕获到的一组输入shape当作likely value 注入编译流程等。
- 由op定义所携带的shape consraint信息。比如:
- elementwise op的输入和输出应该具有相同的大小;
mhlo.dynamic_reshape
op的输入和输出应该具有相同的元素个数;mhlo.concatenate
op 的输入和输出在非拼接的轴上应该具有相同的大小;
- 分析shape计算的IR或者通过传播已有的shape constraint来获得新的信息,比如:
在充分利用上述来源原子shape contraint的基础上,我们可以大幅减少由于shape未知导致一些优化前置条件无法判断,进而导致优化无法生效的问题。
应对挑战3:shape计算开销及更复杂的计算图
在动态shape语义下,会引入更多的shape计算的开销,整个计算图会变得更复杂。
对于shape计算开销,shape结构化约束我们可以抵消大量重复的symbolic计算,从而尽可能减小额外的开销。
对于计算图化简而言,我们一方面可以通过利用shape结构化约束消除一部分的冗余计算,比如前文中提到的由于IB问题引入的大量broadcast op可以在计算图化简中消除。剩下的无法利用shape结构化约束消除的broadcast可以进一步利用以下shape分布约束进行优化:IB触发(即需要插入隐式的broadcast)的概率远小于IB不触发的概率。通过生成带IB和不带IB两个版本的(如下图所示),让common case变得更快,从而提升期望性能;
为什么需要shape constraint IR?
shape constraint在动态shape语义下很有用,但是要用好它却并不容易。由于在整个pass pipeline中都可能会使用到shape constraint信息,因此我们需要一种方式将shape constraint信息在不同的pass之间进行传递。BladeDISC早期时使用是一种隐式传递的策略,即每个pass在需要使用shape constraint信息时会通过分析一遍IR来重建shape constraint信息。不难看出在上述的方案中shape constraint本身并不是IR一部分,这种策略带来的问题是:
- 通过分析IR的方式一般只能够重建(部分)结构化约束信息,大部分的分布约束信息无法通过直接分析data计算IR来重建,而分布约束对于动态shape语义下的性能优化同样很重要;
- 在整个pass pipeline中IR会经历多次的lowering (如TF/Torch dialect -> mhlo -> lmhlo -> ...),在每次lowering的过程中都可能会丢失一部分shape constraint信息,比如下图中所展示的
tf.SplitOp
的例子。在这个例子中上层的tf.SplitOp
会被lower成一系列的mhlo的SliceOp
。根据tf.SplitOp
的定义我们可以知道它的所有输出(假设有N
个)应该具有相同的shape,且输入在被拆分的轴上的dimension size可以被N
整除,这些信息在我们lower到mhlo时如果只进行data computation的转换,而不进行shape constraint信息的转换,将会被丢失,从而使得后续的pass无法再利用相应的信息进行优化;
为了解决上述的问题,我们更进一步将shape constraint 作为第一等公民引入到IR中,使得可以对结构化约束信息和分布约束信息进行统一的建模,同时也确保在整个pass pipeline中各个pass可以看到一致的shape constraint信息,进而更好的支持在不同的阶段完成各自适合的优化。
动态尺寸模型优化实践之Shape Constraint IR Part I的更多相关文章
- HBase实践案例:知乎 AI 用户模型服务性能优化实践
用户模型简介 知乎 AI 用户模型服务于知乎两亿多用户,主要为首页.推荐.广告.知识服务.想法.关注页等业务场景提供数据和服务, 例如首页个性化 Feed 的召回和排序.相关回答等用到的用户长期兴趣特 ...
- 百度APP移动端网络深度优化实践分享(一):DNS优化篇
本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<一>DNS优化>,感谢原作者的无私分享. 一.前言 网络优化是客户端几大技术方 ...
- 腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践
本文来自腾讯前端开发工程师“ wendygogogo”的技术分享,作者自评:“在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦.” 1.GIF格式的历史 GIF ( Gr ...
- Unreal Engine 4 动态切割模型实现
转自:http://gad.qq.com/article/detail/33199 <合金装备:复仇>里面,有一个很有趣的设定,游戏里大部分的场景和物件都可以用主角的刀动态切割. UE4中 ...
- etcd 性能优化实践
https://mp.weixin.qq.com/s/lD2b-DZyvRJ3qWqmlvHpxg 从零开始入门 K8s | etcd 性能优化实践 原创 陈星宇 阿里巴巴云原生 2019-12-16 ...
- vivo版本发布平台:带宽智能调控优化实践-平台产品系列03
vivo 互联网平台产品研发团队 - Peng Zhong 随着分发规模地逐步增长,各企业对CDN带宽的使用越来越多.并且,各类业务使用CDN的场景各式各样,导致带宽会不断地出现骤增骤降等问题.基于成 ...
- 直播推流端弱网优化策略 | 直播 SDK 性能优化实践
弱网优化的场景 网络直播行业经过一年多的快速发展,衍生出了各种各样的玩法.最早的网络直播是主播坐在 PC 前,安装好专业的直播设备(如摄像头和麦克风),然后才能开始直播.后来随着手机性能的提升和直播技 ...
- 携程App的网络性能优化实践
首先介绍一下携程App的网络服务架构.由于携程业务众多,开发资源导致无法全部使用Native来实现业务逻辑,因此有相当一部分频道基于Hybrid实现.网络通讯属于基础&业务框架层中基础设施的一 ...
- Glow Android 优化实践
了解 Glow 的朋友应该知道,我们主营四款 App,分别是Eve.Glow.Nuture和Baby.作为创业公司,我们的四款 App 都处于高速开发中,平均每个 Android App 由两人负责开 ...
- Unity3D游戏GC优化总结---protobuf-net无GC版本优化实践
protobuf-net优化效果图 protobuf-net是Unity3D游戏开发中被广泛使用的Google Protocol Buffer库的c#版本,之所以c#版本被广泛使用,是因为c++版本的 ...
随机推荐
- 后端基础PHP-PHP简介及基本函数
后端基础PHP-PHP简介及基本函数 1.PHP简单介绍 2.PHP基本语法 一.PHP简单介绍 PHP(超文本预处理器),是一种通用的开源脚本语言,标准的后端语言 比较常见的后端语言,ASP|ASP ...
- 2024-03-16:用go语言,给你一个正整数数组 nums, 每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。 (注意,在后续操作中你可以对减半过的数继续执行操作)
2024-03-16:用go语言,给你一个正整数数组 nums, 每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半. (注意,在后续操作中你可以对减半过的数继续执行操作) ...
- 大年学习linux(第六节---软件安装)
六.软件安装 rpm RPM软件包的管理工具 补充说明 rpm命令 是RPM软件包的管理工具.rpm原本是Red Hat Linux发行版专门用来管理Linux各项套件的程序,由于它遵循GPL规则且功 ...
- linux下永久添加静态路由-不同
linux下永久添加静态路由-不同 添加路由的命令: 1,route add route add -net 192.56.76.0 netmask 255.255.255.0 dev eth0#添加一 ...
- App启动流程
目录介绍 1.什么是Zygote进程 1.1 简单介绍 1.2 各个进程的先后顺序 1.3 进程作用说明 2.Zygote进程的启动流程 2.1 源码位置 2.2 ZygoteInit类的main方法 ...
- 冒泡排序【Java】
1 public class Paixu { 2 public static void main(String args[]) { 3 int myNum[] = {2,6,4,1,5}; 4 //从 ...
- Python爬虫爬取全球疫情数据并存储到mysql数据库
思路:使用Python爬虫对腾讯疫情网站世界疫情数据进行爬取,封装成一个函数返回一个 字典数据格式的对象,写另一个方法调用该函数接收返回值,和数据库取得连接后把 数据存储到mysql数据库 ...
- Advanced .Net Debugging 6:程序集加载器
一.简介 这是我的<Advanced .Net Debugging>这个系列的第六篇文章.这篇文章的内容是原书的第二部分的[调试实战]的第四章.这章主要讲的是程序集加载器,比如:CLR 加 ...
- #SPFA#洛谷 4042 [AHOI2014/JSOI2014] 骑士游戏
题目 分析 如果我想普通攻击1,那么必须干掉所有产生的其它怪兽,这不由得可以用一个不等式来表示, \(普攻+\sum need<法攻\) 但是所需要消灭的怪兽同样可以这样进行,所以它可能具有后效 ...
- 这一次,让我们一起来搞懂MySQL
欢迎加入我的专栏,和我一起开始 MySQL 学习之旅. 从日常的开发和优化中,一步步地从一个数据库小白成为 MySQL 调优的开发人员.回想起来,从我第一次带创建索引至今,已经有十个年头了.在这个过程 ...