动态尺寸模型优化实践之Shape Constraint IR Part II
在本系列分享中我们将介绍BladeDISC在动态shape语义下做性能优化的一些实践和思考。本次分享的是我们最近开展的有关shape constraint IR的工作,鉴于篇幅较长,为了提升阅读体验,我们将分享拆分为两个部分:
- Part I 中我们将介绍问题的背景,面临的主要挑战和以及我们做shape constraint IR的动机;
- Part II 中我们将介绍shape constraint IR的设计,实现以及一些初步的实验结果;
本篇是关于Part II的介绍,Part I的介绍请参考这里。
设计和实现
shape constraint IR的设计
使用IR来建模shape constraint并不是一个很容易的事情。我们需要设计一种方案既方便我们做shape constraint分析,同时又不会使得IR的后续变换变的很复杂。经过多次迭代之后,我们选择了type-based方案来构建shape constraint IR,基本思路如下段伪IR所示。
// original data-computation IR func @main() { ... %0 = any_dialect.any_operation(...) : tensor<?x?xf32, [@S0, @S1]> ... } disc_shape.SymbolicDim @S0 { range list : [[...], [...], ...] likely_values : [...] ... symbolic_shape_graph: @shape_constraint_graph } disc_shape.SymbolicDim @S1 { range list : [[...], [...], ...] likely_values : [...] ... symbolic_shape_graph: @shape_constraint_graph } // A separated function to store shape constraint predicates between different symbolic dimensions. // Each symbolic dim is either bound to a `disc_shape.dim` op or `disc_shape.bind_dim` func @shape_constraint_graph(...) { %0 = disc_shape.dim() {ref: @S0} : index %1 = disc_shape.dim() {ref: @S1} : index disc_shape.tie_predicate_divisible(d0, d1) // d0 % d1 == 0 // other tie_* ops // disc_shape.tie_predicate_eq(d0, d1) // d0 == d1 // disc_shape.tie_predicate_lt(d0, d1) // dim less than // disc_shape.tie_predicate_mul_eq(d0, d1, d2, ...) // d0 = d1 * d2 * ... // // d0 * d1 = s0 * s1 // disc_shape.tie_predicate_product_eq([d0, d1, ..], [s0, s1, ...]) // // d0 = affine.apply(d1, d2, ...) {affine_attr = ...} // disc_shape.tie_predicate_affine_eq(d0, d1, d2, ...) {affine_attr = ...} }
在这个方案中,每一个symbolic dimension size(也即在编译期间无法确定具体大小的dimension size)对应一个全局的disc_shape.SymbolicDim
IR对象。该IR对象中存储了关于这个symbolic dimension size的分布相关的约束,同时也存储了对一个shape constraint function的引用。在上图中最下面的部分是一个shape constraint function的例子。在这个function中存储的是symbolic dimension dim之间的相关关系(结构化约束),每一种相关关系用一个op来抽象,比如说这个例子中说展示的整除等价关系便是由tie_predicate_divisible
op来描述。选择type-based方案主data计算图中并不会直接存储shape constraint信息。在上图中的最上面是一个主data计算图的例子。主data计算图中,每一个tensor对应的type中都包含一个attribute,这个attribuet中存储了这个tensor所对应的symblic dimension size的引用。
通过将描述shape constraint的IR和主data计算IR解耦开,一方面可以尽可能减少对已有pattern匹配的逻辑的干扰 (matmul+BiadAdd -> FusedMatmulBiasAdd
这个pattern替换并不需要感知到shape constraint IR的存在),另外一方面,不同层级的data计算的IR,比如tensor level IR和buffer level IR,可以用同一套shape constraint的描述。从而可以缓解IR lowering过程中shape constraint信息的丢失问题。
基于shape constraint IR的优化pipeline
将shape constraint IR作为第一等公民引入IR中之后,我们进一步构建了以shape constraint 为中心的优化 pipeline(如下图所示)。通过对shape constraint的充分的挖掘,而非依赖于具体的shape的值来辅助完成各种优化,从而实现在动态shape语义下尽可能接近静态shape优化工具的性能。
下图中展示了目前BladeDISC中主要的几个优化的阶段。从最左边开始看起。第一步是将前端AI框架的计算图lower到MHLO的计算描述。这里值得注意的是除了普通的data计算的lowering,还包含shape constraint的lowering,从而避免在动态shape语义信息的丢失。到MHLO之后,我们首先会完成shape constraint的分析以及分析结果的IR化表示。分析得到的结果将可以指导我们完成计算图上的一些基本化简,比如冗余broadcast op的消除,layout调整等。优化完之后的计算图,我们会进一步对其中的访存密集型算子做融合优化,shape constraint将是决定那些算子可以融合的很重要的判断依据,通过更充分的挖掘shape constraint,我们可以找到更多融合的机会。最后在做代码生成的时候,我们发现在动态shape语义下index计算的开销更加容易成为瓶颈,尤其是当算子融合的数目比较多的时候,利用shape constraint我们可以大幅消除冗余的index计算。以上限制于篇幅并未一一展开进行介绍,感兴趣的同学可以通过这里了解更多的细节。
初步测试
我们目前已经完成了shape constraint IR的第一阶段开发,也即shape constraint IR的引入以及pass pipeline的适配性改造。第一阶段的主要目标是搭建好整体的架子,还并未包含所有设计中优化的实现 (比如likely value的应用),我们将会在后续持续迭代完善shape constraint IR。在以上前提下,我们在一些比较典型的模型上完成初步的评测,下图展示的是部分的评测结果。由于目前shape constraint IR还未应用到计算密集型算子(GEMM/CONV等)的优化 ,故以下测评针对的是模型中访存密集型部分,主要从两个维度来衡量:
- 访存密集型部分kernel launch的次数,即衡量fusion的粒度,同等情况下次数越少,fusion的粒度越大;
- 访存密集型部分总消耗时间,即衡量生成的kernel的质量,同等情况下总时间越短,质量越高;
如下图中所示,在CPU和GPU上我们都观测到fusion粒度的明显改善以及访存密集型部分总消耗时间的减少。
合作讨论
以上是近期我们在shape constraint IR Part II的分享,更多相关信息欢迎加入BladeDISC用户群交流讨论。
欢迎大家加入 BladeDISC 用户群交流讨论,与我们一起共建。钉钉群号:44534789

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
面向大规模数据的云端管理,百度沧海存储产品解析
导读:本文整理自同名《云智公开课》系列分享,详细介绍百度沧海·存储如何进行大规模数据,流转上云、智能分级存储、安全管理、多业务应用。。 全文5657字,预计阅读时间20分钟。 01 ABC 时代下存储面临的四大挑战 我们称当前这个时代为 ABC 时代。A 指的是我们正处于人工智能的时代;B 指的是我们正处于大数据的时代;C 指的是我们正处于一个万物皆可上云的时代。 存储系统在很多年前就已经出现了,在当下存储又会面临着哪些新的挑战呢? 挑战的第一个关键词:海量。对于企业而言,以前可能只是存放一些互联网上的应用数据,最多就再有一些文本数据,备份数据。但现在,我们看到更多是以视频、音频等为载体,数据量呈现出一个爆炸式增长的态势。在这个背景之下,云服务商面临的是如何解决海量数据的上云和存储问题。换句话说,我们的物理容量如何更好地去承载数据的爆炸式增长。 挑战的第二个关键词:性价比。在这个时代当中,我们将数据视为是有价值的资产。既然数据有价值,那就要求云服务商如何在保证数据不删的前提下,如何帮助客户花小钱办大事,这个是客户以及我们都比较关心的。举个例子,十年前客户的数据是 10 PB, 10年之...
- 下一篇
【案例分享】一次客户需求引发的K8S网络探究
前言 在本次案例中,我们的中台技术工程师遇到了来自客户提出的打破k8s产品功能限制的特殊需求,面对这个极具挑战的任务,攻城狮最终是否克服了重重困难,帮助客户完美实现了需求?且看本期K8S技术案例分享! (友情提示:文章篇幅较长,建议各位看官先收藏再阅读,同时在阅读过程中注意劳逸结合,保持身心健康!) 第一部分:“颇有个性”的需求 某日,我们的技术中台工程师接到了客户的求助。客户在云上环境使用了托管K8S集群产品部署测试集群。因业务需要,研发同事需要在办公网环境能直接访问K8S集群的clueterIP类型的service和后端的pod。通常K8S的pod只能在集群内通过其他pod或者集群node访问,不能直接在集群外进行访问。而pod对集群内外提供服务时需要通过service对外暴露访问地址和端口,service除了起到pod应用访问入口的作用,还会对pod的相应端口进行探活,实现健康检查。同时当后端有多个Pod时,service还将根据调度算法将客户端请求转发至不同的pod,实现负载均衡的作用。常用的service类型有如下几种: clusterIP类型,创建service时如果不指定...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS8安装Docker,最新的服务器搭配容器使用
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8编译安装MySQL8.0.19