ASC 19 回顾(一)

从上周六到这周五,我作为超算团队的成员在大连参加了 ASC 19。最后我们拿到了亚军,总冠军是对岸的国立清华大学。自从 ASC 16 憾失冠军 之后,超算团队已经连续两年赢得了 ASC,去年更是又一次拿到了大满贯。作为今年的第一场比赛,也是我实际上场的第一场比赛,这个成绩也算是开门不利。现在想来,原因有很多,我也当然不能妄下结论。在回京的火车上,回顾这次参赛的经历,其实还是很有感触的。

赛前准备

初赛

由于去年 ASC 没有参加初赛导致决赛的准备比较仓促,虽然我们今年被保送了 ASC,在翟老师的敦促下,我们还是从初赛赛题一发布就开始着手准备。初赛分为三块,分别是传统的性能测试 HPL、气候模拟软件 CESM 和人脸超分。我不是跑分选手,也不太懂炼丹,因此自然就选了 CESM 开始研究。虽然寒假初期就选了题目,整个寒假我都光顾着写 Learn Helper,另外两个选了 CESM 的同学也因为某些原因在摸鱼。因此我们事实上从寒假结束前一周(也是距离初赛 DDL 前三周)才开始正式研究赛题。

我们万万没想到的是,CESM 给我们带来的最大困难正如它的前两个字母:Compilation Error!作为一个科学计算程序,它依赖 HDF5 和 NetCDF 用于存取结果文件,自身的结构也是分为多个组件(如海洋 POP、大气 ATM、冰川 ICE)、运行库。同时,编译结果是与模型选择、计算分辨率、每个组件进程分布等相关的,每次改动都需要漫长的重新编译。我们一开始在实验室的 Gorgon 集群上(用传统方式)编译,花去了大约一周时间。而后我们终于获得了专属的四机集群,回到了熟悉的 Spack 环境。然而 Spack 也并没有一如既往地那么好用,出现了非常多的问题,比如集群缺乏 AVX512 导致程序运行出错,Intel MPI 库无法正常链接,PNetCDF 导致运行出错等。其间另一个同学由于协助博士生投 SC Paper,几乎也总是在摸鱼,于是一周时间又过去了。其中又发生了莫名其妙的 segfault 等情况,后来发现是 ulimit 限制了栈尺寸导致的。初赛共有两个小题,用的模型不同,第二题在运行时居然会从 libc 抛出异常崩溃,后来从 CESM 官方论坛找到了一个补丁,绕过了这个问题。

在最后一周的周四,我们才成功解决了这些奇奇怪怪的编译运行问题。也是在这一周,北大的同学告诉我,CESM 初赛要交的两个模型运行结果,每个要模拟十年,在真机都要跑好几天。我在自己的集群上简单测试了一下,的确如此,所以我们完全是真的跑不完了。再加上很多事情(比如 OS 课程的 Lab)把我们拖到了提交前夜,于是初赛只能一拍脑门,用模型全串行的方法,每个模型跑了几个月,象征性的交上去。到凌晨两点,我才发现还需要从巨大的输出(~50GB)中提取要的数据,于是又用 Python 写了提取数据的脚本。然而第二个小题的输出居然没有我们要的数据,仔细一看 README 是跑之前少加了选项。此时我们又困又累,也无心再跑,丢掉了找不到的那部分直接交了上去。

关于 HPL 和超分题,似乎初赛时的进展都比较顺利,炼丹题更是有三个人在一起准备。

决赛

没过几天,初赛成绩出来了,ASC 组委会发了一个推送,说北大居然使用 GPU 优化了 CESM 的框架,这让我们感到比较紧张。这时候,复赛的另一个应用也发布了,叫 wtdbg2,是一个计算生物学软件,计算基因的配对。由于一位同学很感兴趣,就跑去研究它了,我们的 CESM 小队剩下了两个人。更不幸的是,另一个人再次被博士生抓起来使劲 push,于时事实上又只剩下了我一个人。

虽然看起来初赛到复赛隔了两个月,但是因为三月底我要去考托福,我就多了一个摸鱼的理由。直到四月,我们都几乎没有取得任何进展。其间当然也和不少了解 CESM 的人交流过(比如团队老成员李宇轩、薛巍老师),得到的消息基本都是各个组件的进程映射(称为 PE Layout)很重要,会影响性能(但是不影响结果)。很遗憾的是初赛的两个赛题似乎对这个变化并不敏感,因为不管怎么调整 PE Layout,CAM 组件(一个大气模型)总是独占了大约 95% 的计算时间。还有一个点是不同的向量化(比如 AVX2 和 AXV512)对性能有不同的影响;然而我们并没有任何支持 AVX512 的机器,于是也只能暂时搁置。

这时候,翟老师敏锐地指出了问题:我们应该多跑几种不同的模型,到赛场上才能灵活适应。由于 CESM 输入数据是有限的(或者说,官方认可的只有那么多),但是下载太费时间,所以我们找到薛巍老师问他要了一块有所有官方数据的硬盘。这时候,我们又从实验室机房四处寻找,终于找到了一台闲置的有 AVX512 的机器。我花费了几天安装和设置这台机器,又因为期中考试、期中报告等很多事情不断拖延;另一位同学也因为 SC DDL 的临近几乎失去了响应。最后的最后,直到 4/17,我们才都放下了手头的事情开始专心研究 CESM。

我们沿用了之前确定的分工,即我负责研究 PE Layout 在不同的模型上的性能影响,而另一位同学研究不同的编译选项对正确性和速度的影响。我创建了多个不同的模型,基本都是涉及了所有组件的最复杂模型(这一点在后来证明其实并不明智),然后不停地调整进程映射,运行比较短的时间(比如模拟十天),比较它们的性能。在复杂的模型上,海洋模型 OCN 也会占据大约 15% 的计算量,而它与其他模型都是可以并行的。因此如果合理地分配 Task(对应 CPU)数量,一部分给其他模型串行执行,另一部分留给 OCN,再留一小部分给模块间通信需要使用的耦合器 CPL,当这三部分的执行时间大致相当时,模型的性能表现最佳(比全串行至多快 10% 左右)。一旦三部分不平衡,最慢的那一部分就会是木桶短板,严重拖累整个计算系统的性能。在编译选项上,我们发现 AVX512 相比 AVX2 并没有带来多少性能提升,或许是因为它限制了 CPU 的实际工作频率导致。而另一个意想不到的问题是,融合乘加(FMA)指令虽然能够提高性能,但是会带来结果的误差;产生这一问题的原因是 FMA 指令事实上提高了计算的精度,大量计算的累积与低精度下得到的 baseline 差距过大。关于差距,我们也询问过组委会,得到的回复是一般的编译选项修改不影响,误差在 10% 内即可。但是 FMA 指令带来的误差事实上超过了这一限制。

关于人脸超分这一题,此时已经有四个人在专注研究。他们也找到了符合要求的 State of the Art 成果,甚至还找到了作者要到了原本的代码。由于决赛规则允许带预训练模型,他们的策略是用不同的网络、不同的训练集得到大量模型,最后挑选分数最高的。

而在 wtdbg 方面,两位研究的同学发现它充满了黑魔法(如大量用宏实现线程同步等),因此比较难彻底改成多机的 MPI 程序。同时,我们咨询了原作者 Jue Ruan 老师,阮老师也说没有必要,应当注意一些计算参数的调整。所以,在解决一些比较小的热点的同时,他们也研究了各种参数的变化带来的影响。这个程序还有一大特征是非常占用内存,最大的模型需要超过 1TB 的内存,因此我们甚至无法测试这些模型。

比赛过程

Day -3

时间过得飞快,转眼就到了比赛前最后一个周五。傍晚我们在清华开了最后一个会,集中讨论了一下机器选型等问题。考虑到我们对机器功耗和性能都不太熟悉,最后打算到了现场再最终决定选型。晚上,我们把所有 32GB 的 V100 都拆了下来,一共 16 张。再加上 4 张 16GB 的,总共 20 张显卡分给五个人分头带走,还剩下四张 16GB 的留在家里备用。我们也用科协的 1TB SSD 给 i1 的系统盘做了个备份,并重新做了 i2 到 i8 所有系统盘;我们也把目前家里机器(i1到i4)的系统都又复制了一份到机械盘上,因为原本的 SSD 都要拿走去比赛用。途中于纪平的手还被 R730 的硬盘槽划伤了,三个人总共搞到三点多,途中过程按下不表。

Day -2

中午,我们到北京南站坐上 G497 前往大连。据说东北人有“上车饺子下车面”的说法,所以大家乘车前吃了一份饺子。下午五点到达大连,组委会有接站,我们和北航一起坐车前往大连理工大学。本来报道的地方在北门里面,然而北门不让进车,于是我们坐的中巴就一路绕到南门然后穿过整个校园,权当是校园参观了。报道完以后到酒店入住,然后吃了一顿晚饭。由于不允许进赛场,所以这一天几乎没有做什么。值得一提的是我们发现虽然很久以前给组委会发邮件改了选手列表,然而现场的登记表上还是没有变化,只好手动修改了。

晚上在大连理工的博留餐厅吃饭,是自助的,菜还不错,就是肉有点少。吃饭的地方离赛场有将近一公里的距离,倒是离酒店很近。酒店的环境不太好,不过也还能忍。

Day -1

这一天全天组装机器。早上起床以后去吃饭遇到了台湾清华的同学和老师,吃完打车去了赛场(因为带着大量的GPU)。顺便吐槽一下酒店的早餐,品种很少,也不好吃,只算是能吃饱吧。

赛场很宽敞,环境也很好。进去之后发现虽然我们要了12台机器,组委会只给了10台。每台配置是 2 * Intel 6230,12 * 32 GB,Intel 500 GB SATA SSD,以及 IB 卡。我们一共配置了七台机器,i1 到 i4 每台插 4 块 V100,双电源;i5 到 i7 都是 CPU 节点,单电源。我们给所有机器都上了 eno1 和 eno2 两根网线以提供冗余(防止 SC18 惨剧重演),外加 BMC,再加上选手的机器,居然用完了给的交换机的所有接口。意识到这样不行,就让下午要飞过来的韩导给我们带了个小交换机。本来以为我们有 wired network,都准备给交换机配 VLAN 之类的了,发现 console 线没带,就让韩导又给带上了。不过后来发现我们的集群网络和别人完全是隔离的,所以直接使用傻瓜交换功能也无所谓。

插上我们自己的系统盘以后,我协调了一下自带的 SSD,给每个 GPU 节点两块,CPU 节点一块。由于我们的系统盘只支持 BIOS 引导,所以需要改配置。虽然我们发现了 CSM 选项,但是打开以后引导以后居然直接黑屏了,所有机器都一样。我们百思不得其解,在这件事情上浪费了一个小时,甚至还插上了很早的 CentOS 的系统盘也如此。这其中我们还被叫过去拍了一段宣传视频。后来黄可钊查文档发现除了要打开 CSM,还要把所有的 optional bootrom 从 UEFI 改成 Legacy,果然就 work 了,所以还是缺少配置经验。

虽然系统能起来了,但是我们发现 i1 只识别出了三张显卡,并且还有一张带宽只有 X8,我们加的 PCIE SSD 也没认出来。用了很久排除法(以及等重启)以后,我们发现最右边的两个 PCIE 槽似乎没有用。重新插拔数次以后,我发现居然是 PCIE raiser 到主板的金手指没有插紧。然而解决以后显卡还是 X8 的,非常奇怪。最后细心的yjp发现是 raiser 上面的 PCIE 插槽末端裂开了……!垃圾浪潮毁我青春,我们果断从第九台机器上拔下整个 raiser 换了上去,也顺便把它上面所有内存插到了 i1 上。还有几台机器的显卡带宽也有问题,不过重新插拔以后也解决了。机器都上电以后,i3 的温度(和待机功耗)稳定比其他的要高,初步判断是PCIE线和电源线挡住了风道产生的问题。不过因为不是很显著,所以我们最终也没有完全解决这一问题。

起来以后,网络意外不通,后来发现原本 eno1 和 eno2 是桥接的(因为 SC 没有使用以太网交换机),所以这样接刚好成环了。我把所有 eno2 上面的网线接到了 eno4 上,并且拆掉了桥,把 IP 配置到 eno1 上。于是网络问题看起来是解决了。

我们用六个节点做了一些 benchmark 的尝试,傲傲和 yjp 调了很久的 HPL。我也试着跑了跑 CESM,发现如果不压功耗,刚好稳定在 3000W 以下,颇为惊喜。这一天我们还遇到了著名的 Dan,他来问了机器配置之类的问题,还对我们进行了一段短采访。

为了平衡各个题目的分数,晚上我们做了一张 Excel,评估各种配置(CPU/GPU 节点数量)下各个项目(主要是benchmark/CESM)可能的得分,然后拟合出一个最优的方案。最后我们的选择是7机,也就是 3 GPU 节点(i1~i3)+4 CPU 节点(i5~i8)。这个过程其实是相当有趣的,虽然估计得一点也不准

这一天还发布了团队应用 Fluidity,一个流体力学计算软件。我们的合作队伍是南方科技大学、电子科技大学和华沙大学,因为大家都在装机器,就决定从第二天开始再搞。

下午韩导来了,晚上大家一起在大连理工门口吃了海鲜,餐厅是用 25B 车底改装的,很有趣。菜有点辣,但是味道不错,喝了一种很神奇的叫大开卫的饮料。此外大家还在著名的“连理”中间拍了(单人)照。

Day 0

周一是装机的第二天,也是最后一天。根据前一天晚上决定的配置,我们又进行了大量的测试,我也学习了关于功率控制的一些操作。转眼到了下午,我们决定保留昨天的选择,不过要把大内存转移到 i5 上。组委会要求各个队伍把不用的机器全部下架,也就是说比赛时架子上所有机器必须都是要用的。

一早到现场,因为前一天发现待机功耗有点高,我就重新调了一下 BIOS 的电源管理。原本发现最小功耗模式表现不错,但是 wtdbg 跑起来才发现没有 Turbo Boost;这个程序有一些单线程的计算,所以需要高主频。打开 Turbo Boost 以后性能和功耗表现就都比较让人满意了。

接着,由于昨天只配了6台机器,今天还需要上两台新的机器。鉴于交换机的口实在不太够,我们决定去除所有 CPU 节点的网络冗余,把 i5 到 i6 上面 “eno4” 上面的网线拔掉,插到了新的 i7 和 i8 的 “eno1” 上。当我完成了 BMC 之类的配置,惊讶地发现 i4 到 i8 所有机器网络都不通,甚至连接口状态都是 no-carrier。百思不得其解,我们进行了各种测试,包括重启、重新配置网络、重新插拔网线,发现这四台机器上的网口顺序似乎与下面四台是相反的(注意这不是一个正确的结论)。基于这个结论,我们猜测机器的网卡固件可能有毒,枚举接口的顺序在每次引导时不一致。于是我决定,把 i1 到 i4 上 “eno4” 的网线插到 “eno3”,并且把每台机器自己的 “eno1” 和 “eno4” 都桥接起来,这样无论是什么顺序都能通,并且也能提供冗余。然而一旦拔下来 “eno4” 的网线,前面四台的网络也中断了!到这时我们才意识到,事实上所有机器的网口顺序都和我们认为的不同,也都是一致的。也就是从右到左编号递增。由于我们操作中的种种巧合,这个错误直到第二天才被我们发现。

整个下午都在测试 CESM 和 HPL、HPCG 的功耗控制。由于七点就要交配置单,并且我们还要把目前 i4 上的四个 GPU 借给福州大学,下午五点的时候我们就开始进行一波机器的更改。除了把 i1 多的内存换到 i5,我们还把 i4 和 i10 所有的内存都拔了下来。正当我们准备最后的测试的时候,意料之外的情况发生了,i5 开始疯狂 boot loop,连内存检测都过不去。一开始我发现是几条内存没插好,但是插好之后并没有解决问题。研究了二十多分钟以后,随着七点的临近,我们果断决定换机器,用被拔空内存的 i10 换掉现在的 i5。于是大家又是一波紧张的操作,下架上架、插内存插线、配 BIOS,终于在交配置前二十分钟上线了新 i5。好在这次没有任何问题,只是虚惊一场。

这一天大家还在尝试 Fluidity,各个队伍都编译不能,从依赖库开始遇到一坨又一坨的问题。四个队伍遇到了四种不一样的错,大家都颇为崩溃。南科的一个吉祥物妹子一直来和我们负责这个题的人同步进展,却仿佛是越来越糟糕。我们的负责同学试图在家里集群上直接安装依赖库 vtk,结果它又依赖了包括 Qt 和 ffmpeg 在内的一大堆软件,甚至还导致了系统的 apt 状态错乱。晚上我又试图把它跑在 docker 里面,但是这样就需要把 IB 暴露进去,尝试了各种方法都没有成功,里边的程序始终找不到用户态 IB 驱动。后来我们又有人发现即便不使用 IB,应用本身在 docker 里面也有运行问题。最后,(和韩导一起)折腾到两点多以后,我们队基本决定放弃这个应用。

晚上装机结束以后去吃了 KFC,去的路上看到两家店招牌上下挨在一起,分别是“李先生”和“北辰电竞”,很有意思

这一部分就写到这里,下一篇会讲正式比赛过程,比上面的都更惊心动魄。