TensorFlow开源一年半以来,在GitHub上已经有了820位贡献者,close了5192条issue,还有1033条开放着。
同时,如果所有TensorFlow团队成员都在GitHub上,而且属于这个组织的话,它在Google内部还有着一支75人的团队。
一支人数不算少的全职团队,是如何和数量众多的开源贡献者共同改进TensorFlow的呢?团队的技术主管Pete Warden带着深深的怨念,在O’reilly网站上发表文章,讲述了他们是如何维护TensorFlow开源社区的。
以下内容编译自Warden的文章:
开源可不只是把代码往GitHub上一扔,然后等着别人去用它就完事了。道理我都懂,可直到在谷歌成为TensorFlow团队的一员,我才真正开了眼:要围绕一个软件打造出一个社区,要考虑的因素实在是太多太多了。
社区服务
当一个新的项目刚刚诞生时,在这个项目上能被称作专家的,就只有那些把它写出来的人。他们是仅有的能够撰写文档和解答问题的人,同时,在对软件的改进方面,他们也是最佳人选。
但结果,我们这类TensorFlow团队中的核心成员反倒成为了项目成长的瓶颈。原因其实很简单:我们没法一次性把所有的事情都干完。是,我们确实知道该怎么腾出时间去写代码和文档,因为这本来就是我们在谷歌日常工作的一部分;但要给一个超大社区里的众多开发者解答问题,我们就有点懵比了——尽管我们知道,这对于项目的成功十分重要。
为了确保用户们能够得到他们需要的答案,核心工程团队的全体成员开始轮班。每个人可以从以下几个活里自己挑:处理Stack Overflow上带有#tensorflow标签的问题、检查一遍GitHub上的pull request、给GitHub上的issue分类、同步外部和内部代码,或是找到那些失败测试的原因。
如何分配这些工作由大伙自己决定。一般来讲,如果每个工程师每次在一个特定领域负责一周的话, 我们勉强能让这个轮班机制循环起来。这个机制实行之后,工程师们在他们值班当周的本职工作产出会大大降低——不过至少,每个人的工作被打断的频率降到了几个月一次。
Pull request
我们将TensorFlow开源来让社区能够对其贡献力量。到目前为止,已经有超过400人从外部为我们贡献了代码,这其中既包括简单的文档修复,也包括像OS X的GPU支持、OpenCL的执行、InfiniBand架构下RDMA这样的大输血。首先,每次贡献都会先从轮值核心工程师那里审一遍,以确定其是否真的管用;如果方案通过了最初的审核,我们会对它进行一组Jenkins测试来确保它不会引发任何故障;如果以上两道程序都被通过了,轮值工程师会将方案交给另一位更加擅长相关领域的核心工程师再次进行审核。
在这一过程中,GitHub全新的精细代码审核工具能够为我们提供极大的帮助。而在它出现之前,要把所有人的评价都处理一遍是个十分痛苦的事情。当一名核心工程师与一位或更多的外部贡献者协作时,经常会有更大的pull request会被放入正在进行的工作中。直到每个人都满意之后,PR就会被合并到GitHub上的树顶,并在下一次同步运行时被合并进我们的内部代码库。
代码许可协议
作为自动化pull request程序的一部分,我们会将贡献者的GitHub账号与我们在谷歌开发者网站上的代码许可协议(CLA)记录相匹配,以确保每个外部贡献者都拿到了CLA。我们的目标是是确保整个代码库都在阿帕奇2.0协议下准确无误地得到了分配。当pull request的轮值工程师要对出现的全部问题进行归类的时候,如果一个pull request的内部关联了多个邮箱,或是贡献者需要以团体名义登录,情况就会变得十分麻烦。
GitHub issue
GitHub用户们已经提交了5000多个关于TensorFlow的issue。对于有些人来说,这可能有点让人沮丧;但对我来说,issue却是个最棒的单位——因为它证明,人们是真的在使用这个软件。
为了确保我们回应了每个存档的issue,轮值工程师会时刻查看新出现的信息并试着用标签对其进行分类。如果那是个我们在短期内无法在内部搞定的问题,它就会被标记成“欢迎贡献”;对于一些待处理的bug,我们会给他们按轻重缓急排个次序。这些天来,随着一些外部用户自己变成了某些问题的专家,越来越多的问题没有借助我们的力量就被解决掉了,特别是在像Windows这类我们不会每天都用的平台上。
如果一个issue没能在社区中找到回答或修复,而它的优先级又足够高时,值班的人就会把它分配给团队里一个了解此类问题的工程师。整个TensorFlow团队的成员都有自己的GitHub账号,因此我们可以用正常的GitHub issue追踪器来实现任务的分配。我们确实考虑过把GitHub上提交的bug复制到我们的内部系统中,但要为相同信息同步两份副本,代价太高了。最后,我们让工程师们除了留意内部系统的追踪器之外,也要打开邮件通知,以便能够及时看到自己被分配了哪些GitHub上的问题。
Stack Overflow
Derek Murray是Stack Overflow值班小组的带头大哥,我觉得他回答问题的技能真是碉堡了。根据他的资料页,这个人发过的帖子已经触及到了130万人;为了让我们能够及时追踪网站上那些带有#TensorFlow标签的问题,他还设法创建了一个RSS驱动的自动化电子表格。起初我们采取每周轮班制,但发现要处理问题的量对于一个人来讲实在是太大了;后来我们采用了自动分配系统,情况变得好多了。
我本人就在这个轮班小组里,因此每天早上我浏览完自己的邮件后,我都会查看电子表格来弄清楚自己被分配到了哪些问题。很遗憾,我们没法自己回答全部的问题,但每一个新进来的问题我们都会看。如果问题相对简单的话,我们就自己把它答了。
当然,值班的工程师得顶到被问题轰炸的前线去,但有些时候,回答某些问题需要更多的时间和专业知识。如果某个问题看上去能被答出来,但社区里却没看见站出来的英雄,我们就会研究一下代码,扒一下团队里有谁可能会对这个问题有些想法(通常是用git blame)。然后值班工程师就会向我们找到的人发封邮件,看其是否能提供一点帮助。
邮件列表
我们设置了一个邮件列表,但起初却并不知道该怎么用它。我们很快就看出来,用这种方法来追踪issue和回答一般问题有多辣鸡。
后来,我们把它当成讨论区来用,GitHub和Stackoverflow都不合适的话题,就发到邮件列表,但是在实际操作中我们发现,即便是架构问题,用GitHub issue来讨论也比邮件列表合适。
现在我们用这个邮件列表来发送信息和贴通知,还算是值得订阅的。
代码同步
和我聊过的许多人都对一件事表示十分吃惊——那就是在谷歌内部,我们使用的代码库和我们在GitHub上所开放的几乎完全相同。不过,两者间还是存在一点区别的,比对谷歌专用基础设施的支持是独立的,路径也和GitHub版不一样,但同步的过程是完全机械的。我们至少每周推出一次内部更新,更多时候是下载GitHub版本。
麻烦的是,我们要进行双向同步。在GitHub的公共项目和我们的内部版本上,有很多变动是同时发生的,而我们需要反反复复地把它们全部进行合并。没有现成的基础架构可供利用,因此我们使用了自己创造的一套Python脚本来处理这些问题。这些脚本能够将GitHub上所有的变动拉进我们的内部资源库里,转换所有的header path和其他细微的变化,将它们和最新内部版代码合并,并在内部创建一个副本。随后就可以进行另一个方向的同步了,我们会将所有的内部代码转换成外部的格式,并用相同的脚本把这些结果合并到最新的GitHub版上。
对于内部的修改,我们同样会尽力让每次check-in都呈现为单独的git commit,同时把作者的GitHub账号和解释这些变动的评论包括在内。我们在GitHub上有一个特别的“TensorFlow园丁”账号来完成上述过程,一个内部的commit被转移到GitHub上之后,是这样的:
要确保即使代码变了,这个转换流程依然有效,是很有挑战性的。为了验证这种有效性,我们要求把内部代码通过这个脚本转换成外部版本,再转换回来之后,和最初的内部版一模一样。在任何接触到TensorFlow代码库的内部更改上,我们都会运行这个测试,通不过测试的修改会被拒绝。
对于那些提交pull request的人,我们常常会提一些奇怪的变更要求,通常,这样做的原因是我们必须确保他们的代码能适用于这个同步流程。
Jenkins测试
因为要支持很多不同的平台,我们希望有一个适用范围很广的测试工具。TensorFlow会在Linux、Windows、OS X、iOS、Android、Android Things、以及树莓派上运行,同时我们还有为GPU准备的不同代码路径,包括CUDA和OpenCL支持、以及Bazel、cmake,和无格式makefile的构建进程。
让每一位开发者都在做了变更时手动把上面这些东西全都测试一遍,是不可能的。因此,我们有一套能在绝大部分支持平台上运行的自动化测试系统,这些系统全都处于Jenkins自动化系统的控制之下。始终让它们发挥作用也不是件容易事,因为总会存在操作系统更新、硬件问题以及其他一些与TensorFlow相关的问题能让测试失败。我们有一个工程师团队,专门负责让整个测试系统正常运行,这个团队曾经在系统出问题的时候救过我们很多次。因此在这方面的投入也是值得的。
开发者关系
在开源领域,我们在谷歌并不孤独:我们曾经在Kubernetes和“ 开源计划办公室”(Open Source Program Office)这样的项目上学到过很多东西。有一支非常勤奋的开发者关系专家团队协助我们处理这些事务,他们还承担了很多围绕文档、代码示例以及其他一些开发者经验方面问题而产生的体力活。我们的长期目标是,将关键的专业知识传递到核心开发者之外的范围,以便更多的人能够对社区有所贡献。
让这些核心工程师在部分时间内去承担客户服务工作的一大好处是,它给了我们关于用户所遇到问题的直接洞见。参与客户服务同样驱动着我们去修复那些常见的bug和补充文档,因为它在减少工作量方面让我们看见了直接的回报。
未来,我们希望将这项工作更广泛地进行下去。同时,我们也设计了更多的“战术指导手册”以帮助人们处理常见任务。能有机会同如此多的外部开发者互动,我感觉十分幸运;我也希望,自己能对他们产生积极的影响,帮助他们用机器学习创造新的神奇应用。
关于作者
Pete Warden是TensorFlow Mobile团队技术主管。在加入Google之前,他曾任Jetpac CTO,该公司提供为手机和嵌入式设备而优化的深度学习技术,2014年被Google收购。他还曾在苹果工作,负责图像处理的GPU优化。(完)