深度学习框架的灵魂

转自 知乎 袁进辉

2020年是中国深度学习框架年,清华Jittor,旷视MegEngine,华为Mindspore已经接连在3月份开源,一流科技的Oneflow也在为开源做着紧锣密鼓的准备。国内深度学习框架发展终于迎来了百花齐放的一天,下一步有没有可能发展出具有世界影响力的深度学习框架呢? 无疑,道阻且长,影响因素错综复杂。我前几天写过一篇题为《如何欣赏一个深度学习框架?》的文章,在文中表达了这样的观点:在百家争鸣的氛围下,技术创新性是框架是否能脱颖而出的决定因素。在那篇文章中,我指出了分析框架品质的三个方面:创新性,工程质量,各个模块的技术实现。后来又思考了一下,觉得对框架的分析可以更进一步,我们就在这里讨论讨论一个深度学习框架的灵魂。

任何一件产品都有灵魂,从设计思想到每一处细节,都是这个产品灵魂的表现。一幅画,一本书,一部电影,都在向外传递着坐着的个性主张,同样是暴力美学电影,北野武,杜琪峰,昆汀达伦提诺执导的作品也各不相同。一件电子产品,体现了打造者对产品的想象和热情(如果有的话),这些个性特征也决定了产品的成败。苹果的产品,鲜明地体现了以乔布斯为代表的设计及研发团队的追求;同样作为智能手机,功能类似,但设计不同,即使是抄袭苹果的设计,在制造上仍可能无法像苹果一样做到极致,一部手机有成千上万的细节,苹果可以做到倾尽所有资源把全部细节做好。手机上的每一个APP,也有自己的灵魂,没有人不喜欢微信,微信体现了张小龙产品设计的克制和内敛,绝不乱打扰用户,用完即走,用户感觉到被尊重,没有冷酷和傲慢。

软件系统也有灵魂。软件的灵魂来自背后研发团队对需求的理解,团队的组织结构,团队的审美和价值观。我觉得,Frederick Brooks的《人月神话》一书,对复杂软件系统核心理念的讨论非常好,尽管作者没有使用“灵魂”这个词。Brooks非常强调“概念一致性”问题,我觉得那个“一致的概念”就接近软件的灵魂。

什么是概念一致性?绝大多数欧洲的大教堂中,不同时代、不同建筑师所建造的各个部分之间,在设计或结构风格上都存在着许多差异。建筑师总是试图在前人的基础上有所“提高”,以反映他们在设计风格和个人品味上的改变。所以,在哥特式教堂上,可能依附着诺曼底风格的十字架,展示了建筑师的审美。与之对应的是,法国城市兰斯在建筑风格上的一致性和上面所说的大教堂形成了鲜明的对比,设计的一致性和那些独到之处同样让人们赞叹,这些风格的一致和完整性来自数代拥有自我约束和牺牲精神的建筑师们,他们每一个人牺牲了自己的一些创意,以获得纯粹的设计。这不仅显示了上帝的荣耀,同时也体现了他拯救那些沉醉在自我骄傲中的人们的力量。

实现复杂软件系统的概念一致性绝非易事。康威定律说:组织沟通方式决定系统设计,研发团队的组织架构至关重要。为了实现概念一致性,Brooks高度推崇一种所谓外科手术团队那样的组织形式,设计师或架构师具有权威,有点接近贵族专制,对于开发出美好的软件产品来说,民主倒不一定有益。如果了解微软当年历时五年研发出新一代操作系统内核Windows NT的历程,应该知道Dave Cutler就相当于那个主刀的外科手术医生,正如Linus Torvalds之于Linux操作系统,他们对产品的想象决定了这些操作系统内在的一致概念,决定了对技术路径的扬弃。

软件的灵魂,也取决于研发团队的精气神。开发复杂软件系统是一个马拉松,研发团队需要有情怀才能坚持,需要倾注极大的热情才能出彩。几百上千个日夜,苦心孤诣,精雕细琢,对问题本质的探索精益求精,像艺术家一样,不是为了取悦别人,只是达到自己的心满意足。夜深人静,程序员孤独的坐在电脑前,大脑里可能正发生热烈的化学反应:哦,这是一个有趣的问题,哦,我可能想出来了世界上最巧妙的解决办法,我要亲手把它实现出来。迫不及待要看到效果,半夜灵感来了,都可能翻身起来噼里啪啦敲代码。当然也可能为解决一个bug绞尽脑汁。团队协作免不了碰撞,一个抽象,一个设计,都为了追求真善美,据理力争,面红耳赤,或者因为观点没有被接受而愤懑,或者因为互相挑战,思路螺旋上升,找到了更好的办法。坚持原则,谦逊开放,绝对都是美德。

深度学习框架作为一种复杂软件系统,自然也是有灵魂的。在研究各个框架的过程中,除了关注技术细节,还会琢磨框架背后的人和组织,以及由此决定的灵魂。时至今日,世界上主要的深度学习框架玩家都已露面,谷歌,脸谱,亚马逊,百度,华为,旷视,可以对各个框架的灵魂做一个盘点了。以下分析带有很强的个人主观想象,特别是可能说一些负面的评价,希望不要带来感情的伤害,毕竟每个框架背后都凝聚了一批工程师的数年的心血。

Cuda-convnet

Alexnet横空出世依靠了史前的cuda-convnet,其核心理念是解决大规模数据集上深度学习模型训练速度问题,就是追求怎么把CNN借助GPU跑的快,C加CUDA,模块化不够好,不好使用。

Caffe 和 Caffe2

Caffe使用业界沉淀下来好的编程实践(基于Google style C++,面向对象编程,加上一些设计模式)打造了一个模块化、更灵活的变成框架。Caffe的灵魂在于抽象和模块化。Caffe2 沿袭了Caffe的一些理念,吸收了Tensorflow里计算图的抽象。Caffe, Caffe2项目的核心理念具有高度的一致性,在工程质量上,体现了一种偏好简洁的审美观,排斥过度抽象。但是没有在创新上完成自我超越。

Minerva

班底来自微软亚洲研究院,知道这个框架的人不多,但Minerva可能是最早基于数据流图抽象来实现的深度学习框架。Mapreduce这种大数据系统发展到数据流图,用DAG表示,微软的Dryad系统是这方面的先驱,微软亚洲研究院肯定对这种技术驾轻就熟;Minerva的一个目标是,希望搭建神经网络能像使用Matlab那么好用。可惜的是,在一些关键环节上没有解决好,导致整个系统使用体验欠佳。

MXNet

MXNet前身是几个项目合并而来,CXXNet, Minerva, Parameterserver, Purine2,代表了华人留学生、开发者的精锐。MX表示mix,兼容并包,主打轻量级,不像Tensorflow那么宏大的设定。核心贡献者来自不同的单位,没有绑定关系,是一种松散的合作形式,带头人对全局的设计及技术取舍没有特别强的权威,希望把每位专家的聪明才智都贡献出来,集百家之长,不是Top down的工作方式,是Bottom up的方式,这种方式是有好处的,但同时带来一些副作用,譬如缺乏顶层设计,有拼接感不够浑然一体,概念一致性这一点上是欠缺的(譬如包含重复功能的代码,以及未及时淘汰过时代码)。研发人员兴趣逐渐转移,主创团队的变更,不利于项目稳定发展。

Tensorflow

由程序员之神Jeff Dean领衔的Google Brain研发,之前有Mapreduce, Distbelief等系统,对大型C++项目有精纯的掌握。Tensorflow目标极其宏大,体现了Google作为地表最强团队的雄心壮志,但事实证明,目标过于宏大了。Tensorflow刚出来的一年多的时间,表现都是比较糟糕的(崩溃、慢、不支持多机),但全球开发者已经投降了:好了,就是它了,别人再做框架是没戏了,即使现在比较糟,但以Google的实力,一定可以改好。这就是品牌背书的优势。看Tensorflow代码的感觉是,看局部(每个C++文件,每个类)都无可挑剔,但拼到一起构成一个系统就各种不协调。Tensorflow团队尽管有精神领袖Jeff Dean,但Jeff Dean对框架的深入思考应该是极少的,其实还是一群精英工程师各自为战。我怀疑,世界上没有任何一个人掌握Tensorflow代码的全貌。Tensorflow广为诟病的还有API的混乱及摇摆不定,最近被“民意”裹挟,Keras竟然成了钦定API,这显然不是出于某个一致的设计。给人一种边研发边构思,正如一些美剧,一边播放一边编剧,甚至根据观众反馈来改变下一季的剧情。如果回到最早Tensorflow那篇论文,会发现其实那篇论文有价值的内容不多,写论文时整个团队对问题的思考还停留在表面,看上去是“占坑”之作(当然,Op/kernel, graph, variable,send/recv,图优化,placement 这些都是留下来了)。Tensorflow对一些新思路的支持不够及时,实现了复杂的分布式支持,但用户只想用Horovod,研究员设计了mesh-tensorflow, gpipe,也一直游离在主干代码之外,迟迟没有官方的RDMA支持。总之,Tensorflow是系统工程师主导的项目,体现了精湛的工程能力,对大型项目的娴熟掌控,但对深度学习系统本身的深入思考以及用户真实需求的挖掘这两样最重要的东西被忽视了。患了“大而无当”的毛病,系统太过庞大,算法科学家自身无力推进去新的思路,可能需要很多人协调,删除一些不好的设计也可能遇到阻力。

PyTorch

PyTorch的前身Torch都有十几年的历史了,在Python接口前,有一段时间基于Lua编程。与Tensorflow由系统工程师主导不同,PyTorch由算法科学家主导,甚至可以认为大型C++项目不在他们的舒适区,很多底层接口还是C语言实现,直到最近,才开始做现代C++的重构。也许是因为这些因素,PyTorch很忠实的履行了“如无必要,勿增实体”的奥卡姆剃刀原则,项目伊始基本上不考虑分布式需求(Tensorflow搞了复杂的分布式又如何,用户还不是去用Horovod),也不做静态图编译优化,只考虑单设备优化,大大简化了问题。Tensorflow的API超级复杂,用户相当于要学习一门新的语言,PyTorch将深度学习与Python语言深度整合,充分利用Python语言构造,极端情况下,用户只需要numpy,好的,PyTorch为numpy提供GPU支持,再实现autograd支持,这就完美支持了算法科学家的需求。当PyTorch崛起后,Tensorflow团队应该会有一丝后悔:原来大部分用户需要的如此至少,当初苦心孤诣引入的各种技术全无用武之地。以PyTorch为例,很容易给人一种感觉:wow,深度学习框架如此简单。当然为了运行效率,PyTorch需要在内存管理上做复杂的支持,另外Python指令流和底层kernel计算流之间的异步执行,本质上是CUDA kernel计算时间足够长,就可以掩盖掉缓慢的Python dispatcher的开销,某些情况下效率和Tensorflow不分伯仲。当然为了追求效率,开启JIT优化仍是有效的。算法科学家对大型工程的能力欠缺,但对深度学习算法科学家的需求体会的最深,对需求把握的最准确,核心灵魂就是务实,贴心。天下没有免费的午餐,有些困难的问题是迟早要面对的。

PaddlePaddle

Paddle是国内第一个开源深度学习框架,是国内框架孤独的先行者,可以想见Paddle团队在公司内外曾承担的压力。历经了几代架构师和几个大的版本迭代,最初的设计是Caffe + ParameterServer,当TensorFlow面世之后,在一些基础概念的抽象上模仿了TensorFlow,此后又带有了一些PyTorch的色彩,设计理念不够稳定。Paddle的一个特色是模型库丰富,有来自百度内部各个业务部门的需求反馈和贡献,Paddle在几个国产框架里是模型库最丰富的,甚至给人一种业务模型强过系统核心的感觉,这一般也源自业务部门和基础架构部门的话语权对比。Paddle和后来者Mindspore相比,对无人区探索的勇气是欠缺的。Paddle早期团队很多工程师都不再做框架研发了,让人扼腕叹息,框架研发对工程师造成了什么样的伤害,以至于他们如此决绝地告别这个方向。

MegEngine

MegEngine是一个实现很优雅的框架,我很喜欢。也是历时多年研发,核心团队比较小,但码力很强(我从不止一位旷视同仁那里听到码力这个词),旷视不缺这样的天才程序员,因为主程非常聚焦,所以在概念一致上非常好,精英主义打法的代表。这个框架追求训练推理一体化,推理框架是比训练框架简化的一个问题,以内存优化为例,在简化的问题上容易发现一些优化套路,可以反推到训练场景,一开始解决训练场景的问题反而不好入手。总体上,MegEngine在创新思路上没有超越于深度学习框架的已有认识。

Mindspore

Mindspore 个人带来了惊喜,在众所周知的难题上勇闯无人区,auto-parallel完成度很高,数据并行,模型并行和混合并行。好像我应该算在社区最多鼓吹这个概念,也比较早,但并没有发表论文,近些年Google Mesh-tensorflow, gpipe也都出了论文,之前MXNet团队的Wang Minjie也发过相关论文,斯坦福的FlexFlow等都曾讨论过相关思路,尽管有这些先行者,但完整的在框架内实现出来是非常不易的。Mindspore团队集合了大学教授,2012实验室编译、分布式系统方向造诣很深的架构师,最顶级的工程师团队,既谦逊又无畏,令人敬畏,只要是好的想法,都可以为我所用,如果一个问题很重要,还没有可模仿的先例,也一定不惜任何代价搞定,有人说Mindspore团队说“是一帮狠人”,可以说是非常高的评价了。Mindspore的代码不是那么美观,类似Google style,但细节上并没有严格执行,和Tensorflow一样不嫌麻烦的抽象,这种方式适合大规模协同研发,又一定程度上保证质量。

总结

这些年,和很多人交流过深度学习框架,绝大多数人认为深度学习框架已陷入思路枯竭,没有什么花样可做了,但创新势不可挡,总还是有新的思路出现。框架已进入疯狂弥补自身短板的白热化竞争,同时,有杀手锏创新的话,有可能一剑封喉。国内研发的框架虽然个性还不够强,但已经实现了局部突破,未来可期。等Oneflow开源之后,希望也能写一篇《Oneflow之魂》补全这篇文章。