ASC 19 回顾(二)

这篇是 ASC 19 回顾(一) 的后续,主要讲正式比赛的过程。

Day 1

比赛的第一天,我们早早起床吃完饭就去了赛场,不过直到八点才让进内场。开机执行一些常规检查以后,我们的 ASC 正赛就算开始了。

正赛有功率限制,超过 3000W 就会被要求杀掉当前运行的程序恢复待机功耗。为了避免超功耗和误操作,我们采用了手指口呼和交叉确认的方法来执行一些重要命令(比如程序运行和功耗控制)。首先跑了 HPL,前一天的脚本没有调到位,一上来就爆了两次功耗。仔细调了几次以后,我们在九点跑出了一次比较高的分数,就直接提交了。就在我们找工作人员确认成绩的时候,我开风扇降温不小心超了一点功耗,对方显得比较无语。接着就是按照前一天确认好的流程跑半小时 HPCG,我负责控制三台不跑的机器,压住功耗。九点半左右,我们比较平稳地结束了两个 benchmark 程序的运行。

然后就是当天的重头戏 CESM。这次的要求有三个点,其中第三个点又分为两个小点,分别价值 4/6/8 分。前两个点要跑三十个月,第三个点要跑三年,但是都只用两年的数据来验证正确性。我和郑立言分工开始同时编译和配置这些点,组委会提供了需要的运行数据。很快郑总配好了第一个点,也编译好了。他运行了两天,成功结束,并且发现只需要七秒左右就能算一天,大约一个多小时就能跑完这个点。正当我们开心地增加运行时间的时候,一运行就遇到了从未见过的错误:某个模块报不收敛并退出了。郑总 Google 了很多,都没能找到解决问题的方法。他立刻怀疑是编译选项的问题,于是尝试了各种不同的组合,甚至关掉了整体的优化,但是这个错误始终会出现,只是出现前运行时间长短不一,可能是几天或者十几天,但基本无法跑满一个月就会退出。

于此同时,我也在折腾后面的两个点,编译过程没有什么好说的,但是这两个点一旦运行就会立刻报 segmentation fault,完全无法运行!同样,无论编译选项怎么改,都没法解决这个问题;我多次检查,也不是原本的 ulimit 导致的问题。此时两个小时已经过去,临近午饭,我和郑总开始有些慌了。我提出减少机器数量尝试,但是 6/5 机也都会错误。吃饭的时候,翟老师也提出了各种可能的原因,但经过我们确认基本都排除了,这时候进展几乎完全停滞了。但是从功耗来看,有很多学校已经顺利地运行起了 CESM,这让我们非常着急。

在赛场边上吃完吉野家外卖回去,得知一个好消息:后两个点三机可以运行不会报错!于是我们立刻更换了策略,开始用 3+3 机的方式同时运行 2 和 3_1 两个点。一个多小时过去以后,3_1 居然又出现了 segfault,此时我没有多思考,又开始重新跑这个点(虽然 CESM 每个月保存存档点并允许继续,但是组委会给的性能报告单上写不允许 breakpoint continuation)。此时已经是下午三点多了,第二点的运行已经过半,而如果第三点不出问题,预计也能运行完。

过了将近一个小时,第三个点再次发生了错误。这时无论如何调整,重跑都是不可能的了。抱着死马当活马医的心态,我们去询问组委会,没想到其实是允许从存档点接着运行的。懊恼的同时,我立刻继续启动了 3_1 的运行。一段时间以后,2 运行完了,郑总也一直在试图把 1 跑起来,但是除了一直发生的不收敛问题外,也会遇到 segfault,他对此也是毫无办法。然而我试图在家里的集群上使用同样的模型(+CESM官方数据),却并没有遇到任何运行问题。郑总无奈地询问组委会,得到的答复却是不收敛很正常,一直尝试跑就可以了,“总会收敛的”。我们都感觉很无语,但是时间已经不多了,我们没有再尝试。

在等 CESM 运行的过程中,除了继续研究之外,我也和隔壁 FAU 的小哥聊了一会儿,给了他们几张 TUNA 贴纸,他们好像非常喜欢那张 “In Case of Fire” 的设计。又一段时间过后,正如各位可以料到的,3_1 又双叒叕跪了,还是老问题。但是这次继续运行也立刻会崩溃;经过傲傲提醒,我把读取的存档点往前移动了一个月,就可以顺利运行了。最终,我们在离当天比赛结束还有半个多小时的时候跑完了 3_1,自然也没有时间运行别的了。并且因为 3_1 崩溃多次的原因,我们甚至没有获得精确的时间统计(只在成功运行以后有输出)。我只好为它写了个简单的情况说明,根据我 oh-my-zsh 主题带的时间算了一个粗略的数,交了上去。

趁着比赛结束到断电之前的时间,我们试着跑了 7 机的 HPL 来确认集群的 MPI 通信之类没有问题,从而确认上面遇到的问题的确是 CESM 自身的。我们也把错误日志都发给了薛巍老师和专门研究过 CESM 的学长,他们都表示不应当出现这个不收敛问题,应该是组委会提供的数据被修改得有问题了导致。而崩溃问题也是由于某些模块在遇到特定数据时,计算的正确性会与数据有关系。总之一句话:这些数据点的确都有毒。

超分题的数据集在下午两点发布了,让我们惊喜的是,正是我们所预测的。这意味着我们的预训练模型都是可用的,无疑让我们振奋了一些。

此外,唐适之还是在尝试编译 Fluidity,不过后来其他队伍都放弃了,我们也就放弃了。中山大学弄出了一个 docker 镜像分发给了他们的团队成员,看起来是最顺利的。不过就算我们编译通过了,也没有机时来运行它了。

这天晚上,我们还是在学校食堂吃饭,简单讨论了一下第二天的对策,大家都对第一天的结果不是太满意。因为没有什么好准备的,这一天睡得很早。

Day 2

比赛第二天的开头很戏剧性:由于和我住一个房间的人手机闹钟因为神奇的原因没有响,我们醒来的时候已经是八点多了。大喊 woc 之后,我们立刻起床冲向了赛场,大概在八点二十左右抵达。

前一天的成绩在上午九点左右就发布了,最初的成绩是我们 HPL 第四名,HPCG 第三名,CESM 也是第四名。HPL 最高分是北航,跑出了 50T;HPCG 最高分是 NTHU;CESM 最高分是 SYSU,有 12 分(意味着他们跑了 4+8 两个点,并且性能最优),而我们只有 5 分多。看到以后,我们都很沮丧(甚至我和郑总看着分数一脸愁容的照片还被主办方拍下来了)。但后来形势又略显好转:主办方算错了 CESM 的分数,所以重新发布了一版新的分数,这次我们变成了第三名,得到了将近 8 分,意味着我们前一天并没有跑得太差,但是性能分依旧有相当多的损失。无论如何,还是需要继续努力。

这次的神秘应用叫 ShengBTE,是一个计算声子热导的软件。本以为在编译上会为难我们,但是我到赛场的时候队友已经成功编译起来了。所以我们就用最小的一个点测试它的扩展性,反复运行几遍以后发现扩展性奇差无比,三机和七机运行时间所差无几,只比两机稍快一点。我们观察到这个软件有一个非常长的初始化过程,之后才是迭代计算,所以认为可能是因为点比较小,计算量小,所以扩展性比较差。找到了一个跑过这个软件的物理系同学咨询,他也说对于大数据扩展性不错(事实证明我们不应该轻易相信如此)。我们还在配置文件里面找到了一些号称大幅能够影响运行时间的参数,但是因为它说可能影响精度(实测的确也影响),就没有想要去修改。不过我们的测试还发现如果总进程数是某个参数的倍数,性能会有下降。没有时间细究原因,不过还是很庆幸绕过了一个小坑。

在我们编译测试的时候同时,负责 wtdbg 的同学们也开始了运行。与之前我们的研究不同的是,这次组委会给出了 24 个点,使用同一份数据和不同的运行参数,也就是说我们完全没有调参的余地。由于 wtdbg 可以 load 中间结果,他们先用两机完整运行了两个(互相不能 load 的)点,然后打算用 5 台左右的机器并行运行每一个参数组合,并使用最开始 dump 的两份数据。由于这个应用的 IO 压力也不小,并行运行也不需要共享大量文件,我们用上了每台机器原来带的 SSD 存储,把中间结果复制过去即可。不过在 load 时,我们遇到了不少麻烦,刚好有空的我通过读代码和文档发现了需要运行一个 server 来提供共享内存,解决了这个问题。wtdbg 的功耗曲线比较神奇,在最后阶段会有几个峰值,不过我们成功错开了几个并行的程序的峰,也通过 CPU 功耗控制基本压住了功耗。神秘应用的表现比较稳,甚至开始迭代以后 CPU 功耗还会下降。

到下午两点半左右,我们跑完了 wtdbg 的所有点和神秘应用的所有小点,只剩下分值为 3、3.5、4 的三个大点。途中虽然发生了一次 Ctrl-C 的误操作和一次超功耗,不过没有带来太大的影响。我们就开始用 3 机跑 3 分点,4 机跑 3.5 分点。我们刚开始跑,南科的吉祥物妹子就来告诉我们他们跑 4 分点的时候遇到了“内存泄漏”失败了;猜想最大的点大概就会有各种问题,我们没有太在意。开始运行以后,功耗曲线呈现出了非常显著的特征,每隔 9 分钟左右会有一个大尖峰(此时我还没有意识到发生了什么),导致我们神经紧张,不过好在一直没有超。

四十多分钟过去以后,3 分点居然因为内存不足被杀死了!主办方告知“就是会这样”,我们立刻意识到了情况的严重性。因为发现每个进程都会吃掉相当多的内存,我们想到的第一个办法就是减少每机器进程数量,同时也通过 swap 来做兜底。我们研究得到这个结论花了一段时间,这时候 3.5 分点也运行完了,我们就开始用 7 机运行 3 分点(极其错误的决定),把进程数降低到每机器 30。此时我们非常紧张地盯着内存用量,但是持续半个小时都在 8 GB 左右。正当我困惑的时候,突然机器的功耗疯涨到了 2950W。手忙脚乱地压住功耗以后,发现就这几秒钟里,内存用量涨到了 270GB!这时我才反应过来功耗尖峰是快速大量内存分配导致的。正当我庆幸熬过了这一次,内存又开始疯涨,直接超出了物理内存的极限,进程纷纷开始 D 住,swap 开始工作。由于我们有一台机器有 768GB 内存,我们可以发现它事实上需要 500GB+ 的内存,而 swap 的速度实在是太慢了。等了大约十几分钟以后,我们只能杀掉了它。

我们终于明白,唯一方法就是再降低进程数。而此时已经四点半多,我们还在愚蠢地寄希望于它的扩展性,坚持 7 机运行(后来我知道,这个决定事实上让我们告别了冠军)。此时南科已经运行完了 4 分点,听到这一消息,我们决定赌一把全力跑这个点。把进程数控制在每机 20 以后,终于能够顺利运行了。然而运行一个多小时后,我们绝望地发现,这个数据要在五个温度上进行迭代,每个温度的预处理+迭代至少需要半个小时,而 4 分点只有一个温度。到这时,我们知道已经无法挽回,只能硬着头皮跑下去。最后,我们交的数据也只有这个点两个温度的结果。

这一天我们也没有给超分题分配多少机时,只是用所有带来的模型 infer 了结果,并对于每一张挑选了表现最好的。最后我们在验证集上的距离大概是 0.87 左右。

就这样,正式比赛结束了。我们把所有机器恢复了原状,收走了卡。当时我们把所有卡都摞起来的场景成功吸引了 FAU 几位国际友人的注意,他们纷纷表示赞叹并给我们的卡拍了照。顺便一提,今天又送出了几张 TUNA 贴纸。其中一个 FAU 的小姐姐表示她昨晚给男朋友看了以后他很喜欢,想给男朋友带,真是突然一嘴狗粮。我还发现 FAU 小哥穿着 FAU Security Team 的衣服,聊了聊发现他们也搞 CTF,感到比较意外。此外他们看着我们的 Grafana 眼热两天以后终于也自己搭起了 Grafana 监控功率,大概是因为主办方提供的实在太不好用了吧(甚至还会内存泄漏)。

晚上我们又去火车海鲜餐厅吃了海鲜,还是一如既往的辣。吃完以后大家集中在一起准备第二天的答辩 PPT,准备到零点多。晚上我们也和其他队伍有了一些交流,得知 SJTU 使用 Distributed Shared Memory 的方法把 wtdbg 改出了多机,性能几乎是我们的两倍。由于大家的基础性能都差不多,而这一题性能分又是归一化到 $[0,6]$ 区间,这意味着我们几乎得不到性能分。而进一步又听说 SJTU 通过修改一些参数运行完了神秘应用,这让我们更是感觉到被全面碾压。总之,不用说冠军,连亚军仿佛都成了奢望。

Day 3

由于第二天答辩抽签排到倒数第二,所以第三天可以晚点起。我们十点多才动身前往答辩的地方,是一个很高端的酒店。答辩过程还算顺利,不过傲傲在被问及一个修改带来的加速比的时候,错误理解了负责队员提示的 2%(by 2% 理解成了 to 2%),闹了个不大不小的乌龙。

答辩完是十二点半多,主办方提供了简单的午餐(真的非常难吃)。由于颁奖典礼两点半开始,我们就打算出去玩一圈看看海。傲傲从酒店边上租到了一辆车,带着我们开车在附近转了一个多小时。大连的路网的确比较神奇,经常出现“右后”这样的方向,也有非常多陡峭的山路,开车的体验不算是非常好。回来的路上,我们经过了一片海滩,下来看了真正的海。但是当天风特别大,大家都被吹得七荤八素,大概十五分钟就回到了车上。

回到酒店,到了颁奖典礼的场地,首先看了很多段过去的视频。典礼开始以后,一如既往的介绍领导、讲话,花了半个多小时。而后观看了今年的比赛总结视频,也看到了我们装机第一天录的那些片段。接着就是最让人紧张的颁奖环节了。虽然我们都没有抱着太大的希望,但是每个应用的得分前列学校名单却与我们的预估并不相同,并且一等奖名单里面居然没有我们(以及 NTHU),SJTU 却出现在大概第五名的位置,SYSU 是一等奖第一名。这意味着我们居然排到了前二!这是超出了我们期望的,大家都变得有些激动了起来。不过因为这次的表现的确不佳,我们也并没有进一步的希望。

等一等奖漫长的颁奖仪式过去,单项奖也都发完以后,就剩下亚军和冠军没有公布了。主持人念出“亚军”两个字后的三秒钟显得尤其漫长,尽管有 99% 的把握,此时我还是让 1% 的希望占据了我的大脑。当听到“清华大学”的时候,我反而倒是松了一口气。接下来就是领奖、合影、大合影、和许多人合影,很快颁奖仪式就结束了。有一个有趣小插曲是,其他的小奖杯都有专门的盒子盛装,亚军和冠军的大奖杯反而无处安放。

仪式后,傲傲和韩导去接受媒体采访,剩下的人和其他学校的同学们都开始交流起来,主要是关于自己这一次的详细情况。从 SYSU 得知,这次 CESM 的不收敛问题和 segfault 问题都可以通过巧妙修改进程数量和映射实现,这让我们极其惊讶,因为官方文档明确指出这并不影响计算,这让我进一步肯定数据存在问题。而 SJTU 之所以成绩不佳,是因为他们对 wtdbg 的修改有误,导致正确性出现问题,得分很低;而他们的神秘应用修改的参数也不在允许范围之内,因此也比较惨烈。我们自认为比较稳妥的超分题,事实上得到的结果并不突出。NTHU 在第一天与我们差距并不大,高 1 分左右;第二天神秘应用和超分两校也都差不多,他们的制胜点在于 wtdbg,移除了所有不必要的 checkpoint 输出,得到了最高的性能分。

晚上主办方给所有选手举办了晚宴,规格看起来比较高,菜也相当不错。酒足饭饱以后,大家开始在饭桌间互相走动聊天,散发小礼物。我带的 TUNA 纪念品(包括贴纸和徽章)此时也都发完了,非常受欢迎。我们和很多学校的同学们都聊得很开心,包括 FAU、CUHK、SYSU、电子科大、山西大学等等,大家都很很友好,也很有趣。FAU 那位一直和我聊的小哥还和我加了 Telegram,他说会在 SC19 当志愿者,期待我们能再次见到。CUHK 的一位同学还开玩笑地问 TUNA 下掉 Anaconda 源是不是因为 ASC,大家都笑了。不过从聊天中也能看出来每个学校的条件都不一样,很少有像贵系这么高的支持力度。因此这次遗憾败北还是感觉有所愧疚的。

转眼就晚上八点多了,组委会提供的回宾馆的大巴就要发车了。于是大家依依不舍地告别了(还有一些同学选择留着继续喝酒聊天),坐车回到了宾馆。因为第二天要早起赶车,我就在楼下买了个面包,而后收拾了行李。我的 ASC19 之旅到这里就结束了。

写在最后

说实话,作为第一次上场的新人,我之前完全没有任何比赛经历,因此遇到问题总是很慌。事实上,我们遇到的问题别人几乎也都会遇到,所以冷静的处理才是帮助团队获胜的关键。很多人说 ASC 的获胜关键是求稳,这是非常有道理的。我们起初最看好的 SJTU,表现耀眼,却因为激进的优化半路翻车;而 NTHU 虽然没有如此突出的表现,但是他们正确地把握了比赛的节奏,对问题的处理冷静而合理,一举获胜。或许就像傲傲说的,我们还是太缺乏经验吧。

其实想说的还有太多太多,写下来却都变成了流水账。那就这样吧,权当是对我第一次参与超算比赛的一份记录。

补充

收到组委会的总成绩邮件,惊讶地得知我们总分离 NTHU 的差距只有 1.2 分。这意味着事实上只要 CESM 或者神秘应用再跑过一个点,我们完全可以夺冠。这件事情让我的心里的愧疚进一步加深了,因为但凡改正任何一个上面提到的错误的决策,我们大概率就可以翻盘。只是事到如今,马后炮或者后悔并没有什么用。吃一堑长一智,人生大概就是如此吧。

后来也和 SYSU 搞 CESM 的同学交流过,他们是真的下了苦功,改代码优化,现场也试了很多不同的进程数量。事实上它在 2 的幂次进程数下面表现很好,性能甚至比占满 CPU 核数还高,也没有出现不收敛或者 segfault 之类的问题。问题还是出在准备不足啊。他们今年也会去 ISC,我们也需要更认真地准备了。

不管怎么说,ISC19,加油!