作为友商,并且是做相同方向的友商,再加上最近关于AI框架开源的节奏很热闹,忍不住也来蹭个wifi,表达些观点:)

纯技术讨论,不涉及其他,部分我拿不准的地方,会直接以(?)标识出来,欢迎菊花厂同学来指正解惑。

华为的运营同学蛮专业的,在回答里介绍了一些比较重要的技术细节,哪怕不看code,对于做这个方向的同学,也大概也能捕捉到里面的一些core concepts,YongCHN同学也对MindSpore的auto parallel部分有一个小调研,也可以供感兴趣的同学了解。

最近关于AI框架开源的讨论比较多,包括Jittor和MegEngine以及MindSpore,所以我想还是尽量能够提供一些有额外信息量的输入。

  1. 从框架的设计原则上,个人认为MindSpore还是蛮中规中矩的,能够看到明显从TF,PyTorch里分别借鉴了两家的经验(不要忽略MxNet的Gluon,其实也是把静态图和动态图结合在了一起,可惜这两年日渐势微,其实也从一个侧面反映出引擎技术核心以外因素对AI框架推广的重要性,参见这里的一个回答,更不要忽略了Theano这样的已经deprecated框架里早就有的静态图的渊源以及当年还小引领过风骚的Chainer)。都是做这个方向的,就不客套了,官宣里提到的将python的模型描述JIT编译成计算图的思想,在Google的JAX/auto-graph以及PyTorch的TorchScript相关的工作里比较早就已经touch了,不过有决心去从头build并落实,这个还是值得点赞。

2. 如YongCHN同学关于auto-parallel的分析里所说,在TF里,为了在python层加入auto-parallel的支持,同时还兼顾TF 2.0的eager mode,在python代码里引入了大量的 if (eager_mode) 的判断,让整个代码的可维护性受到了不小的影响,而TF为了加入Distribution Strategy的支持,对其现有的python构图代码也做了大量的修改和插桩,其实让整个框架的python层实现复杂了不少。而MindSpore的整个code base,在auto-parallel的实现上能够感觉到还是清晰了不少,引入了ANF这个IR层(关于ANF的设计理念之前自己并不了解,感谢@叶子豪 同学的输入,稍微补了些课,相关的background材料可以参见这里和这里 ,也对照著重新看了一下ir/anf.h里的定义,认为设计动机确实如ANF的背景材料所说是为了简化source-level的变换复杂性,关于细节,这方面不是我的expertise,如果有了解的同行能够share更精准的理解就太好了),把分散式策略的工作有不少沉到了以ANF IR这一层,避免把python API层改得太惨,这个设计认为是更合理的分拆,也确实在没有历史包袱的框架里更容易make这样的design choice。站在前人的肩膀上总是能够也应该有更好的创新。

3.在我的理解中,MindSpore的架构层次大体上可以拆分为

  • ME(Mind Expression)
  • Graph Compiler
  • 运算元库(GPU/CPU平台上的比较常规,Ascend上是对CANN运算元库的封装,只不过在代码库里只看到了少量的CPU运算元和GPU运算元的实现,Ascend的运算元实现则没有看到源码,没有理解错的话,是通过拼装JSON串作为输入再通过一层bridge获取到对应运算元的执行码,对应的具体执行码目前并没有开源出来,说得不对请花厂同学指正)
  • Runtime

这几个大层次。

从git repo的组织来看,ME、运算元库(部分运算元库目前以闭源.so的方式提供)基本都放在MindSpore的主体repo里,Graph Compiler和Runtime放到了GE(Graph Engine)的repo里。按官网的doc似乎主要的fusion工作是在GE里完成的。但是呢,一些涉及到运算元fusion的逻辑又散在了MindSpore主repo里,同时也在GE的repo里看到了一些fusion的pass。这让我稍微有些curious为什么是这样组织。从架构设计上,会感觉fusion相关的逻辑应该统一放到GE的repo里才自然。

目前我能够推测出的一个原因是GE主要target Ascend硬体,对于GPU相关的fusion不属于GE的范畴,所以在 MindSpore的repo里针对GPU的fusion做了一些比较直接的工作(?)

4. 整个执行flow从代码结构来看是这样的,

  • 用户完成python层的模型构图
  • 调用python层的train API(mindspore/train/model.py)以后,会通过pybind11的介面触发 ExecutorPy::Compile(),在这个函数的实现里,会将用户python模型描述的AST解析成ANF的格式(了解JAX和auto-graph的同学就能看到相似之处了)
  • 完成ANF graph的构建之后,剩下的事情就比较自然了,在这个graph上bla bla bla做一系列的transformation,直到生成一个编译好的byte string,并将这个编译好的结果序列化保存下来
  • 再通过一个pybind11的介面触发ExecutorPy::Run(),对上面的编译结果进行实际运行。

这个流程其实蛮自然的,至少在JAX和TF auto-graph项目里都有类似的作法,在PyTorch里其实也有类似的尝试,核心的难点我认为是在于Python的语法太灵活了,于是在不太起眼的AST2XXX(XXX可能是TF GraphDef,可能是JAX里的HLO graph也可能是MindSpore里的ANF graph)这个步骤可能会出现大量的corner case。PyTorch通过python解释器和PyTorch核心交互调用的方式(算是一种trace的方式)来牺牲一定性能但根本性的避免了这个陷阱,而JAX也好,auto-graph也好,以及MindSpore也好,在想获取动静结合的组合优势的同时,也需要pay for对应的engineering cost。

5. 当前开源出的结果里,model zoo还是偏少,这其实不难理解。AI框架演化到现在这个阶段,我个人认为,哪怕是为一个新的硬体平台,从头开发一个AI框架的核心idea也都已经基本是显学了(扒扒TF/PyTorch的code,读读相关的system design的paper,有精力兴趣的话再去刨一下Chainer/Theano/MxNet相关工作的材料,主流AI框架的核心idea也就拿到了),难点其实在于如何结合具体的硬体平台以及业务场景将构成框架的各个pieces有效地组织起来,获得好的trade-off。这背后有著大量的系统设计和工程架构的要求。之前Jittor刚出来那会儿,有商汤的朋友在朋友圈里感叹说两三个可以做一个AI引擎,我对这个观点持很大的保留意见,如果说两三个精干的人搭一个能够跑通几个public model的AI引擎原型甚至在个别模型上有不错的性能表现我没有任何疑问,但从跑通几个模型到达到工业级生产水准,我认为还有著巨大的宏沟需要跨越(性能的鲁棒性,计算结果正确性,训练到推理链路的完整和流畅性,从云到端不同设备覆盖的广阔性,针对不同场景的架构设计的妥协等等,背后都对应著比较巨大的工程资源的投入),这里先不展开了。

6. 关于材料中提到的整图下沉的技术点,确实需要承认,当能够自已掌握从硬体到软体全链路时,系统的整体优化空间变得就更为广阔,整图下沉就是一个例子了。在DaVinci的晶元,配备了ARM的cpu,就使得加速器上也具备了通用计算的处理能力,四个CPU core跑一个OS,四个CPU core跑一些不适合DaVinci的Scalar/Vector/Cube计算特点的逻辑(比如一些条件控制逻辑甚至IO预处理逻辑等)是一个听起来make sense的技术点。这里可能有一个小的陷阱是,在AI作业里,有些时候,对CPU的算力需求可能会比较大(比如IO或网路通信),甚至超过DaVinci的片上ARM CPU的算力capacity,这种情况下,MindSpore在DaVinci晶元上的性能表现就更值得关注,也是更考究系统设计鲁棒性的地方了。系统设计没有magic,每一个晶体管,每一个cycle,用到这个地方以后,就不能再用到另一个地方了。软体系统的设计也类似。当然了,花厂有很强的硬体自研能力,如果说未来的晶元会引入IO core或对AI晶元上的通信能力进行强化,进一步offload对片上通用CPU算力的需求,让整个AI作业的执行过程尽可能不要跳出片子,我倒是也不会意外。不过另一个设计维度也许是,不一定要求作业执行过程完全不能跳出片子,而是通过一些机制来保证当作业部分执行环节跳出片子,也能进行性能补位(类比GPU设计理念里通过高Occupancy来确保可并行调度的计算需求足够高,来缓解消隐访存latency开销的作法)也许是一个可以考虑的点。Again,这里的难点在于设计trade-off的抉择,比如说作业完全在片子内能cover性能是100分的话,如果不能cover,是期望对这类作业退化到90分呢,还是退化到80分但同时反过来把那10分的余量用于确保片内完全能cover作业的性能达到120分?这需要结合workload趋势理解,软体栈系统把握能力,以及硬体架构设计,用至最终的硬体工艺实现来进行一个全局的把握,是一个值得玩味也迷人的复杂系统设计问题。

7. 对于MindSpore背后的计算密集运算元相关AI编译的工作,其实还有著比较强的兴趣想进一步了解,即对应于TBE(以及TIK(?))背后的工作,不知道未来是否也会开源出来。

先写这么多。

最后声明一下,以上理解,完全基于周末对MindSpore的代码层阅读理解,很大可能会有偏差,还请相关同学指正。


2020.4.3 更新】:我孢B站上线了!后面社区例会、在线分享等活动的录屏都会上传,尽可能保证我们所有讨论的公开可获得性,方便开发者查阅。社区例会对于我们来说也是一种新的尝试,昨天Data SIG做了第一次试水,来自中加的开发者中英文混杂的讨论,可能不像一般上游社区例会那样有序,但毕竟是迈开第一步,求大家弹幕轻喷:)

哔哩哔哩 ( ゜- ゜)つロ 干杯~ Bilibili?

space.bilibili.com

大家好,作为MindSpore的社区运营负责人,来还愿(怨?)了。前情可见:

如何评价华为全场景AI框架MindSpore即将开源,能否超越Tensorflow和Pytorch??

www.zhihu.com图标

说实话即便对于无脑黑,我也是非常感激的,因为在冲刺准备的3月,和他们的对话给我带来了无尽的欢乐,极大的缓解了压力,还帮我们做了免费的预热。本来想安排这次扯淡事件中爆火的我们可爱又超牛的TommyLike同学,提交initial commit,打一打某些人的脸(除了此前话题下面的各位喷,还有像这位同学这样的

后来想想那阵沸腾鱼乡般的热闹暖场,还是应该心存感激才对。

闲话少说,书归正传,再扯多了又该被批评不懂开源偷偷去听Tensorflow seminar了。。。不想搞很长的贴,官网资料[1]或者公众号很多软文都可以看,这里就挑MindSpore两个最重要的层面:Frontend Expression (简称ME) 和 Graph Engine (简称GE)来说说MindSpore一些主要特色吧。

ME:

ME采用模块化方式描述网路,采用及时编译(JIT)的方式将Python描述的网路静态编译成计算图,提高网路被执行的效率。

自动微分方面实现了一种通用的基于源码转换(SCT)的自动微分,可以做到支持全部主要的语法结构(闭包,函数调用,条件跳转,循环,递归等)。

并且在执行前对反向计算过程进行静态分析和图优化,这样可以提前规划计算任务和数据搬移以及优化掉冗余的计算和内存开销,达到最佳的执行效率。

在此基础上,支持自定义梯度和基于剪枝优化的stop_gradient以及可控制反向传播的梯度hook,来满足不同场景的自动微分需求。

基于graph-based IR在表达性上具有高度的灵活性,甚至可以做到打破图跟运算元的边界,把运算元侧的一些优化提前到图优化阶段来做,达到图算联合优化效率。

ME编译得到的计算图是device无关的,针对不同后端进行特化,可以在Ascend、CPU及GPU等多种不同的后端上进行训练和推理。

GE:

图引擎的核心设计理念是以并行和资源为中心,即挖掘模型计算的并行性,高效映射到计算/内存资源。以下两个设计是当前MindSpore性能关键。

Pipeline并行:训练中的每次迭代包含多种计算处理,包括数据处理、前向/反向计算、梯度聚合等,充分的并行是发挥硬体中多种引擎算力(Scalar/Vector/Cube/Comm)的关键。GE图拆分基于引擎代价模型自动映射图节点,实现不同子图之间全非同步,比如log/metric处理和前向计算全非同步,数据处理和前向/反向计算全非同步,反向计算和梯度聚合全非同步等。同时GE设计上解耦图表达和计算引擎,新增引擎自动注册即可实现网路图在新引擎的并发映射,适应晶元未来架构。

TF 2.1实验性支持CollectiveHints(bytes_per_pack)来强化反向计算和梯度聚合的全非同步从而减少拖尾。MindSpore基于升腾组网实现自动融合通信,无需开发者指定Hints。

Horovod: fast and easy distributed deep learning in TensorFlow这篇文章通过Host侧MPI控制融合策略,需要引入gather和broadcast同步,对于算力强的晶元这个同步开销不可忽略,也不适应能够整图下沉的晶元架构。

整图下沉:得益于升腾晶元的创新架构,图引擎针对高性能训练场景使用整图下沉设计,即图优化的结果一次下发到晶元,无需在Host上通过图Runtime分发op,极大减少交互开销。这对GE图优化能力提出极高要求,类似传统VLIW中的静态指令调度,每个task的排布都要充分对齐晶元资源利用。GE图优化既实现通用优化(比如const folding,CSE,代数化简、数学融合等),也实现硬体感知优化(Stream分配/Memory分配/Task编译/Buffer Fusion等),特别支持包含控制流结构的网路图的优化和硬体映射。Format是Tensor的基础属性,也是NPU硬体设计的性能选择。GE实现以重开销运算元为锚点的扩散演算法,实现整图的全局format最佳适应,匹配运算元的硬体偏好实现性能最佳,并最小化转换开销。MindSpore GE的图优化是业界第一个支持NPU的开源图引擎。

Show Me The Code

当然,直接撸代码是最好的体验方法。MindSpore目前提供了pip、源代码、docker(CPU,GPU)[2]等多种安装试用方法[3]。4月份我们会开始提供升腾开发者环境的体验,但开发者即便没有GPU或者升腾910的环境,在CPU上也能验证MindSpore的简单构建和执行。只不过有时候三方库的下载可能会有些慢,如果大家都遇到这种情况的话,去提一个ISSUE,我们在社区给大家把缓存弄好。

我们也准备了一个很挫很基础的基于kubeflow 1.0和kubernetes 1.14版本的MindSpore Operator[4]实现,熟悉kubeflow的开发者可以按照README中的步骤进行一个超级简单场景的复现,大致体验一下MindSpore的容器化部署和运行。MindSpore Operator这个坑我们会一直填下去的。

如果在试用过程中有问题,请先移步我们的FAQ,如果FAQ不能帮到你,请直接在ISSUE区按照模板提交ISSUE。

为了方便海外开发者参与,我们在github同时维护了一个镜像仓[5],并且开放了PR和ISSUE的提交。

代码相关的许可证采用的是很多开发者所熟悉的Apache 2.0,文档和书籍中的非代码内容,则使用了CC-BY-4.0的许可证。

总体来说,MindSpore还很年轻,开源不是终止符,开源只是万里长征第一步,后面要和大家一起走。

更多有趣好玩的东西

大家在代码仓[6] 可以看到,除了主模块外,我们也开源了可视化工具MindInsight,模型对抗性安全评估工具MindArmour,如果有对国外主流开源社区玩法比较熟悉的同学,还可以看一下我们设计的开放治理模式[7] (我们的TSC由来自中国、欧盟、英国的14名专家组成)。请大家在参与社区讨论(无论是ISSUE、PR、slack、mailinglist还是微信群)之前,仔细阅读我们的Code Of Conduct[8] ,做一个懂得开源社区社交礼仪的参与者。

写在后面

对于我们这些常年混迹上游开源社区的人来说,做开源的本质其实就是做内容,只有做好了内容,无论是选择商业、非盈利还是其他模式,都不会太差。我在之前帖子的回复中也提到过,我们这次准备MindSpore开源也是想尽全力把内容做好,但是这个内容的维度,实际上往往是超过技术本身的,它包括了技术项目、社区基础设施、网站、社区治理模式、文化建设等方方面面的事情。希望我们这次提供出的,是一份合格的内容。

我们也经常会被问及各种比较的问题,其实对于开源人来说,与你死我活的产品营销不同,我们更希望通过交流、合作,碰撞出有趣的新的idea出来,所以比如最近开源的Jitor和MegEngine,对于开源界来说都是极好的事情,我们也在想和这些很牛的开源项目挖掘出一些合作点。之前在启智OpenI开发者大会的panel中,我跟Oneflow的袁老师说,特别希望两者有没有可能结合起来,MindSpore负责貌美如花(开发与部署体验),Oneflow负责挣钱养家(大规模集群并行的编译优化),如果能有这么一种解决方案的话,岂不是太好了。顺便推荐袁老师最近的一个帖子:

袁进辉:如何欣赏一个深度学习框架??

zhuanlan.zhihu.com图标

2020年出生的MindSpore,感恩前人的积累,野望AI的新方向。

(例行广告,欢迎加入我菊的头孢大军:) -

社会招聘 | 分散式并行计算实验室?

mp.weixin.qq.com图标华为海思 | 社会招聘?

mp.weixin.qq.com图标

参考

  1. ^https://www.mindspore.cn
  2. ^https://gitee.com/mindspore/ms-operator/blob/master/README.md#mindspore-docker-image
  3. ^https://gitee.com/mindspore/mindspore/blob/master/README.md
  4. ^https://gitee.com/mindspore/ms-operator
  5. ^https://github.com/mindspore-ai
  6. ^https://gitee.com/mindspore
  7. ^https://gitee.com/mindspore/community/blob/master/governance.md
  8. ^https://gitee.com/mindspore/community/blob/master/code-of-conduct_zh_cn.md


为什么大家不约而同的造轮子?那一定是现在还有很多没有解决的问题。

问题1,目前的AI框架难以支持如雨后春笋般冒出的AI处理器;tf或者pytorch能很容易的支持一个新的AI加速器吗?tf或者pytorch演进了怎么办,重新迁移一次代码吗?想想这个代价吧。第二种选择,那就自己造个框架,支持自己的晶元。HW这种巨型玩家,居然既要又要,也是服了,真有钱。

类似的,我们看看gcc和llvm是怎么支持一个新的硬体的?经过几十年的发展,淘汰了很多编译器,最终gcc和llvm二分天下;在这个过程中,传统cpu的设计也逐渐趋同,使得编译器能做到比较容易的支持一个新的cpu。而中立的编译器一旦出现,最早的编译器玩家,例如IBM、intel会逐步转向开源编译器。

但是做过DSP或者其他古怪的晶元的同学,发现gcc或者llvm支持起来,需要很多定制化的修改。类似的AI晶元支持和GPU的支持,对框架开发来说,难度也不可同日而语,HW同学可以谈谈体会。目前的AI晶元架构应该还处于早期发散阶段,所以诞生一个能支持大多数架构的中立的框架,从客观上讲还需要一定的时间。

因此在这个阶段,自己做一个框架支持自己的晶元,甚至去尝试一下成为未来的gcc或者llvm,是一个理所当然的选择。目前猜测HW应该意在AI晶元的生态。

问题2,抛开AI生态,框架其实还有不少问题,运算元和图层隔离,需求跨度太大(运算元库在厂商手里,自定义和优化难),对新应用的发展不利,同时物理分层,难以全栈优化。TVM、MLIR等项目的诞生,也是想解决这个问题,自定义运算元,运算元优化,全栈优化。就拿自动微分来说,你很容易使用tf和pytorch的python api组一个运算元,自动生成微分运算元出来,但是这个肯定没办法直接跑在AI加速器上,有产能没性能。如果你用cuda或者加速器的介面或者运算元开发语言手写一个运算元出来,性能还不错,但是有性能没产能。如果有一种既有产能有又性能的方式出现,这是一个巨大创新。

问题3,框架的IR设计还没有成熟。运算元IR应该设计成粒度,使用什么样的抽象来组织?这些问题在现有的框架中都没完整、成熟、通用的方案。jittor xla都在尝试解决和优化这些问题,但还是有缺陷难以克服(运算元粒度太小,丢失信息融合回不去了)。

问题4,优化还是比较adhoc。相比传统编译器中的理论和演算法,AI框架的优化手段不值一提,全是pattern match!而这个方向上,出现了传统编译里面类似迭代编译的技术,所以我们看到autotvm,TASO都在尝试用AI的方法来做编译优化。但是这些方案只能离线使用,在线还是需要类似传统编译的演算法或者cost model。

问题5:框架难以支持更复杂模型。对控制流,高级数据类型的支持和优化还比较弱。这是一个鸡生蛋和蛋生鸡的问题。很难说是制约著谁。或许只有框架支持了,更多的应用才会诞生。


先点个赞啊,看了一眼代码和例子,感觉完成度非常高

一些感想

  • 比起pytorch,其实mindspore更接近于tensorflow
    • GHLO对应了TF HLO,下面的图执行引擎对应了xla
    • 编程的python介面类似于keras/pytorch lightning,通过model+封装好的optimizer/callback来进行训练。这样做的缺点是需要定制训练过程的时候会损失灵活性,优点是利用现有常见的训练方法更容易,而且非常容易扩展到多机多卡上
  • 粗看了一眼Source code transformation似乎完成度非常高(但是没看到详细例子,建议多加点例子到doc里)

亮点

  • MindInsight(link)从截图来看比Tensorboard功能更丰富,那么多年了可视化终于可以有了新选项……
  • 并行策略丰富(link)
    • 支持model parallel/混合modeldata parallel,这方面现有框架都做得比较少,不知道mindspore在引入这个之后性能有多少提升?
    • 通过Cost Model, 同时考虑内存的计算代价和通信代价对训练时间建模。这个之前只在论文里出现过,算是第一个开源工程实现?从之前华为的DawnBenchmark排名来看这个对多机效率的提升应该还是比较明显的
  • 支持混合精度
    • 这个tf和pytorch(apex)都支持。对于bert之类大模型横行的年代,混合精度还是非常必要的
  • 模型安全(link)
    • 实现了一套提升训练robustness的pipeline,算是人无我有的新功能吧

总的来说在现在这个时间点,mindspore的技术选型丝毫不弱于tensorflow和pytorch(具体实现水平等mindspore多拿点比较数字出来再吹),该有的功能也都有了,很有希望!


推荐阅读:
相关文章