夏日记事
上周准备完ASPLOS的投稿,虽然十天以后又要到处做报告而我的PPT还只字未动,但是我仍然悠闲地坐在屏幕前打《英雄无敌3》。
十五年前也是像这样的夏天,我跟三两好友挨家挨户地玩英雄无敌(还有帝国时代,红色警戒,NBA Live等等),各家父母都只让孩子玩两三小时,互相串门就有了七八个小时的游戏时间,想必家长们也心知肚明。 不同的时候打游戏通常有不同的目的,大四那会儿玩塞尔达和巫师3,多半是为了排解gap year的焦虑,而玩手游则纯粹是为了社交和消磨时间。把游戏当作第九艺术来欣赏是需要消耗精力的——而搬砖人们不配消耗自己已经被压榨无多的时间,这也可以解释为什么《英雄无敌》变成了一个没有任何商业价值的IP。
西雅图的夏天是宜人的——高纬度,温度不算太高,六点日出九点日落。吃完晚饭之后去Burke-Gilman Trail上骑车,一路都有树荫遮蔽阳光,城市的景色尽收眼底。假如未来世界格局不会有太大的变化,我是愿意和雨荷在这里一直生活下去的,当然,夏天还是得有空调。 相较于国内的内卷和(偏恶性)竞争的氛围,这边似乎看不到大家脸上的焦虑,学生们到了四五点该去锻炼的去锻炼,该去开party的去开party。正在赶论文的我与这样的反内卷氛围自然是格格不入,索性这一个月都闭关宅在公寓里赶实验和写论文,当然,每天还是花出了一个小时来锻炼,多年的经历告诉我,所有折损身体的行为都会遭到反噬。
回到这次投稿,这次的工作是(又一个)稀疏运算的编译器,虽然年初时Luis就已经定了投ASPLOS这个目标,累计的工作量和实验结果也足够,但是在投稿期间依然有些匆忙。 稍稍做个复盘,开发上,今年做了两个很重要的决策:
- 把单阶段的lowering改成了渐进式lowering,以便更好地分析读写区域和解耦sparse iteration和sparse buffer。
- 支持了混合格式,并将其实现为了一个pass。
第一点大概在年初时就决定做这个重构,将近三月底完成(后期又重构了几次),而第二点则是在五月才成型,此时距离投稿只有一个多月,而实验部分只有一些"proof of concept"的结果,规模化的评测还没有开始。 好在最后一个多月里我们没有遇到本质的困难,虽然工作量很大,大部分的评测都非常丝滑地完成了,而少部分的bug基本上都在一天之内解决,这得益于我们多级IR的合理设计——系统规模越大往往越能体现什么设计是正确的。睿航学弟非常给力,并行地完成了tensorize的实验和TACO的评测,这还是在他有另外两个项目要忙的前提下,不禁让人感概有一个优秀的合作者是多么省心。
事实证明,这两点都是我们论文中非常重要的卖点,天奇将其总结为"composable format"和"composable transformation",以区别于之前的TACO等相关工作,我个人认为是非常贴切的——面对往后硬件异构化的趋势,可组合性是编译器端发力的关键。我们工作最主要创新点则是在中间表示设计上做了合理的取舍,将稀疏运算的不规则性由编译器来分解到硬件的不同异构单元中,可以预见这里有很多的算法问题可以做,当然这些都留给后续工作好了——SparseTIR提供了一个脚手架,一个后人的baseline,这是我理想中的系统工作,挖坑告诉大家这里有很多low-hanging fruit可以摘,而不是照着几个benchmark使劲调参,以证明自己的算法的优越性。
总体来说,这篇工作的开展过程还是相当紧凑的,虽然这两个决策都有风险,在当时我是没有办法预测这些重构是需要多久才能做完的,以及他们的后续影响。不过抛开是否能赶上deadline而言,发现设计有误其实是好事情,这意味着有一些本质的地方我们一开始没有考虑到,设计这个系统并不是trivial的(相应的,写作的时候需要得当地说明)。 这个工作从开题到投稿大概花了一年的时间,25k行的系统实现和10k+行的评测,大致符合我对于一个扎实的系统工作的预期,后续合并至上游和维护应该还需要不少的精力,预计将一直持续到2023年底,这个工作才可以算告一段落了。Auto-formating是一个好的算法问题,我打算让正在跟我合作的大四本科生一起尝试一下这个想法,自己挖的坑,还是要带头填一个。
如果说有这个流程中什么不满的地方,虽然最后两位老板们还有Sandy花了很大的精力重写故事+提高这篇文章的可读性,但是我仍然认为第三节的展示方式还有很大的提升余地,下次投稿务必要更早地把初稿(不管有多烂)交给合作者们,因为自己闭门造车通常会陷入思维怪圈,尤其对于篇幅较长的论文而言。 天奇和Luis在改论文的时候都让我学会了很多:系统(或者其它领域的)论文一般只讲一个卖点,堆砌式列贡献则会被认为不够聚焦,也增大了审稿人理解的难度。一个好的故事应该是这样:
- intro前一半
- 我们要解决的问题是什么,有什么挑战
- intro后一半
- 为了解决这个挑战,我们提出了一个核心方法(对于我们的论文而言,核心是composability),简要解释它为什么能解决我们的问题
- background(可选)
- 对于一个全新的问题,需要简要介绍背景
- overview
- 我们搭了一个系统来实现这个核心想法,概括如下…… (时刻不要提及忘记与核心贡献的联系),有些作者喜欢在这一节加一些启发性的例子(motivating example)
- our approach
- 详细解释这个系统的各个模块
- evaluation
- 做足够详细的实验来表明你的核心贡献是重要的,图例字体要大
- related work
- 尊重你的相关工作,并表明跟你的工作的关系,说不定给大家带来启发
- future work(可选)
- 我挖了个坑,这里是一些可能可以填的坑,我不一定做,你们可以做
- conclusion
- 再复读一遍这篇文章
也就是说,纵使系统实现上有很多贡献,也不应该列菜单似的写在introduction里面,好的故事需要一开始就让读者聚焦在核心的部分,一篇论文也是。写作顺序上,对于我这类一开始无从下笔的新手而言,可以先写our approach, related work和evaluation,因为这些模块相对而言可以变动的余地比较少。而overview则是需要精雕细啄的,需要一张很直观的大示意图(放在第二页),让(与你方向相近的)审稿人一眼能看出你的贡献是什么,这次投稿天奇对这张图提了很多轮的意见,最后终究是能比较明显地体现出我们与TACO这类传统稀疏编译器的区别。Introduction则是新手不是很容易把握的地方,写了许多版,老师们都不太满意,最后由几位老师重新组织思路改成了以“composibility”为核心的故事。Introduction的确非常重要,之前邀请了志强和玉炜来做proofread,他们都表示我这个intro写得有点弱,重点太散,而他们都对于相关工作比较熟悉,对于非小同行审稿人而言,一个不够好的intro可能会让他们完全失去重点,甚至误解一篇论文的意思。 abstract-introduction-overview-our approach这四节的关系是——前者是后者的缩略版,而写作顺序则可以是从后往前开始,abstract可以留在最后写,因为文章比较成熟以后写摘要是水到渠成的事情,犯不着还没有开始成文的时候浪费时间去想。
做这个工作的过程中成熟了很多,我也不再像以前一样把潜在的对手当成敌人,一方面我意识到自己的贡献是独特的,不会有被人scoop的风险;另一方面,做一个编译器类型的工作还是应该团结各个群体(HPC/ML/Sys/Arch/etc)的人,这样才能有影响力。马上要去Google的MLIR团队介绍我们的工作,他们有一个跟我们同期进行的工作,我希望我的工作能给他们带来启发,同时我也会去思考TVM和MLIR的生态有没有什么成本比较低的方法融合起来。
刚刚提交了qualification exam的申请,也就是说下半年我就要成为Ph.D. candidate了,如果沿着稀疏编译这条路线走,我相信我花不久就能毕业,但是这个愿景似乎不够大。我希望去尝试重构一下硬件设计的软件栈——设计更好的前端语言,语义上能与应用相匹配,后端则连接已有的模拟,测试和验证生态。定一个小目标:下一篇论文要是best paper级别的。
一个好的工作是能被人记住的,就像《英雄无敌3》一样。