0%

SC21回顾 - 赢了,但只赢了一点点

SC21又又又又是在线上打的。第二年痛失美帝免费旅游机会了!!!第二年了!!!没有机票,酒店,和大吃大喝的比赛能叫比赛吗!不过结果还是不错的,远远的超出我的预期(原因请看下文分解)。

SC20:没有什么比这更绝望的了

时间回到去年,我并没有给SC20写回顾,因为这场比赛打得实在是——太!烂!了!烂到以至于取得了倒数第二的优异成绩,烂到了我都不好意思把这个比赛写进简历里,烂到了我到SC21开赛的时候才去问SC20的成绩。尽管SC20是我们第一次参加的SCC,但不至于烂的这么有特色。上一场比赛出现了包括但不限于以下这些情况,

  • 完全不存在的赛前准备,虽然时任队长已经尽力在准备Cyclecloud的环境了(甚至去研究了cluster-init),但其他队员似乎就完全没碰过云环境(伏笔1)
  • 两个16级的跑路了(不过当时拉他们过来的时候,也说好了他们可以当placeholder)

我自己那时候负责的是复现挑战,不过我当时根本就不知道复现挑战要干嘛,甚至把精力放在了改代码上。我用了GDR来优化GPU P2P通信来着,还觉得自己挺牛批的来着(伏笔2)。Webinar完全没有看,到了比赛的时候才知道要“在46小时的时间里写出具有发表在国际刊物水平的report”。我作为一个无paper选手(截至目前也还是没paper),用Excel都画不明白的那种,到了场上才发现——坏了。

要复现的论文里提出的程序MemXCT有CPU和GPU的版本,比赛要求用两个版本跑出来的数据画图写报告。GPU版本这边,由于之前完全没用过云集群,我完全不知道云上预装了什么东西。队长在强力推销他的HPCX OpenMPI库,而我自己在测试的时候用的是NVIDIA HPC SDK里的OpenMPI。我一想,HPCX是NVIDIA的,HPC SDK也是NVIDIA的,它们的OpenMPI应该是同一个东西吧。结果很显然,MPI炸得很灿烂,程序就是死活都跑不起来。在无穷无尽的MPI调参和重新编译,MCA的各种参数各种排列组合都试了一圈以后,嗯,没有什么效果。套GDB单步慢慢调,去找爆炸源(那一会我还不知道GDB可以直接Traceback),发现就是我改的GDR P2P那几行代码炸了,但HPCX的OpenMPI不是自称是CUDA Aware还支持GDR的吗,年少无知的我并没有对HPCX产生怀疑,从第一天开始,一直瞎勾巴试到第二天晚上,才想到用回NVIDIA HPC SDK试试。MPI一换,什么问题都没有了。得益于这段时间里,我享受了长达4个小时的精致睡眠,我的大脑throttle到完全没有意识到“放弃这个优化”这个操作(且复现题压根就不需要优化),哪怕是其他Application,把程序跑起来才是重中之重。

CPU版本这边,总所周知(并没有),我们可以用mpirun的各种各样奇奇怪怪的参数(如ppnmap-by)或者Job Scheduler(如Slurm)来绑核。然而当时我既不懂Slurm,又不懂mpirun的参数,完了这程序还是Hybrid的(MPI + OpenMP),需要给MPI Rank分配多几个CPU核,而不是1个Rank一个核。我一顿操作猛如虎。好消息是,程序跑起来了。坏消息是,程序以一种很奇怪的姿势运行在多个节点上,比如明明要跑四节点,却出现了一节点有难,三个节点围观的情况。

到了比赛快结束的时候,两边才正常跑起来,由于根 本 没 有 提 前 写 论 文,也 不 知 道 怎 么 画 Academic的图,要不是有一个临时安排的帮手,在比赛结束前report写不完也就算了,估计连张图都画不出来。由于交的实在是太晚,这堆学术垃圾在提交到一半的时候比赛就结束了,这样也好,这篇完成度极低的黑历史就再也不会有其他人看到了。

其他人那边也没好到哪去,由于赛前准备什么的基本不存在(人还跑路了),Applications不能说是一塌糊涂,只能说是亿塌糊涂,基本上拿不到几个分,CESM跑不出,GROMACS只跑了一点,倒是MiniVite似乎还行。最后只能寄希望于Benchmarks,把剩下的Funding All in到Benchmarks上,说不定还能捞一个单项奖。当时他们刷了半天HPL,最后刷到了120TFlops,混到了暂时的第一,反手就被ETH的129T打成灰了,反手反手就被半夜想搞大新闻的THU搞出了大新闻,300T打得灰都不剩了。与此同时T队的HPCG,IO500分也把榜打爆了,这两玩意的分数是当时榜一(可怜的靶子)的3.89倍,5.76倍,似乎看到了摩尔定律复活的希望。在这种分数差面前,我们并没有任何反抗的余地,只能对其深夜5am炸鱼的行为表示强烈的谴责。

赛后才知道,HPL和HPCG方面,T队几个月前向组委会提交的plan里,早就盘算着把Azure机房洗劫一空,只要我GPU堆得越多,跑分速度就能快到其他队连尾气都闻不到,只要我操作够快,火速开机火速关机,一大堆GPU也花不掉几个钱。并且充分考虑到V100节点不够的问题,也准备了转用其他GPU节点的预案。组委会许可了他们的方案,并搬出板凳坐等看戏。反倒是我们的HPL因为超规格的问题,被扣分扣成了倒数。IO500更是离大谱,自研了打榜专用文件系统MadFS(详见金枪鱼之夜——IO500 S: There is rjgg behind MadFS - YouTube),科研成果下放到学生超算竞赛,直接形成降维打击,不得不说THU的System方向真是tql,TUNA里个个都是人才,说话又好听。

总之,要不是SC21打得不错,我是再也不会去提SC20的事情了。

SC21 Phase 0:队友人呢?

今年招新的结果非常意外,忽悠到了一些《建议直接颁发硕士毕业证》的20级新人。今年招新是让感兴趣的入队的人做一份笔试题,目的当然是选出愿意去了解这个领域并去做一些搜索的人,由于计系没有哪门课介绍了超算,我对于他们的预期就是《言之有理即可》,aka《有字就行》,结果出现了这种情况,

Neko.d> 同学你好,由于你以一己之力让我怀疑题目出得太简单了,所以我希望今天能和你当面聊一下…

怎么会有人开局(大一)就几乎啥都懂啊,那还要我们老油条干嘛?

但另一个问题出现了,这次招新一个妹子都没忽悠到,不像去年又有Female还有Transgender,Diversity直接拉满,四舍五入直接等于保送进决赛。今年我们队里现在全是臭男人,proposal就只能尬吹我们辉煌的过去。

在写proposal的时候,本想把任务拆分,先写个中文的大纲,offload给其他队友,让他们输出English paragraphs,再merge成一个完整的proposal。结果真到offload的时候,赶作业的赶作业,赶paper的赶paper,这也就算了,还有去外面嗨然后装死的。当队长这个大锅抛到我头上的时候,距离交proposal的ddl已经没几天了,还得去拉浪潮的赞助。发现队友都指望不上还没时间自己搞定的时候,我只能无能狂怒,

Neko.d> I AM REALLY ANGRY!

但我angry并没有什么用,proposal还是得写,最后想到了一个惊为天人的解决方案:用谷歌翻译把提纲翻译一下,我看两眼改一改就交上去了,反正我只要坚信reviewer不喜欢看一大段一大段的屁话,我的良心就不会痛。

几个月以后收到消息,令人意外,我们用脚写的proposal过了,倒是T队挂了(不过靠着ISC冠军又回来赛场了,你大爷还是你大爷),听说还有几个国内的强校也挂了,目测多数死于Diversity。虽然我们Diversity吃了一个reviewer的低分,但其他的reviewer好像成功的被忽悠过去了。参赛前务必把美式政治正确玩明白了。

SC21 Phase 1:还能抢救一下

众所周知,我是摸鱼之王,摸鱼从来就没输过,摸到组委会专门发邮件催我们上号,摸到连队友不敢摸了。

组委会> Azure说你们从来没有上过号。马上比赛了,想问问你们是不是网络不好,登不上号啊?有问题的话要跟我们说啊。

组员1> 所以什么时候练习啊

组员2> 所以什么时候练习啊

Oracle集群的试用期也就五天,到账号激活的第二天我才想起来还有这事(我紫菜)。集群配置比较常规,主要是不存在伸缩问题,在试用的时候没发现太多的问题(主要是因为很多东西没来得及试)。

一个不大不小的事故是,因为我想让队员在练习的时候熟悉Linux的账号机制,就让他们改passwdsudoer.d。然而我低估了修改sudoer.d的风险,因为这个东西改炸了sudo就用不了,想还原sudoer.d的配置来抢救sudo本身又需要sudo权限,好家伙死锁了。不得已,只能寻求场外援助,Oracle的Technical Leader,Marcin老哥。老哥一看我的问题,见怪不怪,熟练的向我们推销serial console下grub改bootargs init=/bin/bash之术,想必他的客户自己(哦是我啊,那没事了)也没少搞炸系统。当grub的界面显示在Windows Terminal下的时候,我大受震撼,这还是我第一次看到在serial console下的grub,而且还保留了原汁原味的TUI。改好参数,顺利以root身份登录系统,直接把写坏的配置删掉就完事了。

Marcin> :) Sysadmin Sunday

Neko.d> Oh. Sorry to disturb your beautiful Sunday morning lol.

Marcin老哥是个大好人(会救我们的人是好人,周末来救我们的人就是大好人啦!),此外他还教我挺多实用的东西,比如,

  • 一键关掉超线程
  • 一键添加集群账户(集群预装了LDAP的东西)
  • playbook自动化工具(据说可用于重装部分软件)
  • ssh-agent

到了Azure这边就没那么幸运了,赛前中后和其他队的运维瞎聊,大家无一例外的碰到了,

  • cloud-init更新的配置不被应用。公认的workaround是,要想改cloud-init脚本,重建集群吧!也就等十多分钟就好了!很快的!这导致我不敢写很复杂的init脚本
  • image的一堆坑
    • VM的世代数和Image支持的世代数不一致,需要手动指定隐藏镜像OpenLogic:CentOS-HPC:7_9-gen2:latest(后来发现这还是个陈年已知问题,上一任运维知道,但不说)
      • 有个好心人给了个魔法PowerShell指令来捅出镜像列表
    • 只有CentOS 7.9的镜像带了驱动,8.1的没有
      • 可以自己装驱动,GPU部分不仅需要GPU本身的驱动,还需要NVSwitch的驱动,叫Fabric Manager。如果NVSwitch的驱动不正常,会报一个cudaErrorSystemNotReady的错
        • 补充:驱动的安装程序和安装目录不要都在NFS盘上,建议把全家桶拷到本地盘再安装,能大幅提升安装速度
      • IB部分可以装OFED全家桶(还有坑,伏笔)
  • 魔改过的Slurm会在VM发生不明原因初始化配置超时的时候把好不容易allocate到的VM释放掉,尽管VM能正常使用。(每次开节点都要排十多分钟的队,然后大概率配置超时,这谁顶得住啊)

值得一提的是,我们几个运维一致认为Azure的技术支持Andy是个装死带师,我们三个都被Andy无视了。跑去跟SCC主席Kathleen complain,

Kathleen> 啊,Andy早在Webinar里说过自己最近忙了,你是不是没去听啊

Kathleen> 还有你们Stand up meeting跑哪去了

彳亍口巴。Andy告诉我唯一有用的东西就是,CycleCloud Console的cloud-init脚本可以不是cloud-init脚本。

实际试用的时候,Azure上来就是开幕雷击,先是遇到了世代数的那个问题。到比赛快开始的时候才开GPU节点练习,(因为A100很贵,27刀一小时,而且队员之前没准备好,还没把CPU版折腾清楚),这个时候才发现CentOS 8的镜像要啥驱动都没有,自己一装驱动又踩了NVSwitch的坑。搞了半天还搞不定,仔细一想每次开VM都要装驱动,难顶,只能碰运气看看7.9带不带驱动。还好驱动是全的(似乎也是唯一一个带全驱动的镜像)。降系统版本又造成了一些小问题,什么缺Lmod导致module load intel全家桶出锅啊,什么GCC版本太老导致C++ ABI出锅啊,好在这些问题还是能解决掉的。

除了被两边集群的“特性”折腾以外,似乎没有太多问题了,也就记得有

  • Spack会把tmp目录挤爆,改TMPDIR环境变量就可以了
  • Spack不会自己更新和确认过时的编译器信息,然后还把错误的信息缓存了,需要clean一下bootstrap就好了(spack clean -b
    • NVIDIA HPC SDK也有类似的问题,Any changes to your gcc compilers requires you to reinstall the HPC SDK
  • 默认情况下nfslock没启动,导致No locks available

其他队友那边,一开始大家还自信得一批,仿佛人均编译带师,到了自己编译应用的时候,尤其是用Spack编译一些依赖(e.g., 比如OpenBLAS和FFTW)的时候,或者要编译GPU版代码的时候,编译器就能给你炸得妈都不认识。只好各种换编译器换姿势编译,什么GCC,ICC,ICX,NVC都用了一圈。年幼无知的队友甚至还对AMD有一丝信任,想用AOCC和AOCL平替,结果我就不说了,懂得都懂。最后发现还是老一套,ICC+MKL稳如老狗。(其实是一开始我忘装了MKL,所以让他们先试OpenBLAS,然后就欣赏编译器烟花了)还有NVCC经常会选错Host编译器,得加--ccbin啥的。总之,你永远不知道最终生成的看上去能运行但大概率会爆炸的二进制文件是几个编译器生成的代码缝合在一起的产物。

SC21 Phase 2:演我们?

Azure试用到没钱的后一天就正式比赛了,可见我们什么时候才开始赛前准备。按照基本上等于废话的计划,第一天开局打算先让复现和Cardioid跑,总之就是先把Oracle集群用起来,反正没有预算限制,QE和神秘应用这种要花Azure钱的晚一点再上也不迟。9.30am有个meeting,还以为要公布instructions了,结果除了打一个尬飞了的招呼以外,什么事都没发生,instructions一个字都没看到(后来才意识到这个meeting是用来把我们骗进breakout room然后给其他人直播比赛事故现场的)。

不得不说今年的instructions有点随意啊,不仅公布时间随意,而且,

  • Submission的instruction甚至直接用的去年的,一个字都没改
  • 有一题的instruction放在GitHub上,放出来不久又改回private返工了

这潦草的instructions让本来就因为remote而显得不正经的比赛看起来更不正经了,好想打场正儿八经的SC现场赛啊,但没机会了。Anyway,比赛还得打。

Cardioid

assign的同学巨屌无比(还是20级的),基本上可以称为修bug自动机,因为他有NVRTC和LLVM+PTX瞎搞的经验,这题就扔给他做了,总体来说没有遇到太多的问题(因为bug都瞬间被修掉了导致我对其并没有什么太深刻的印象)。

  • 在测试的时候就发现跑GPU多节点会出问题,但Oracle上只有一个GPU节点,那没事了。Cardioid似乎有几个variants,但只有一个能跑,但比赛就只用那一个,那又没事了
  • Cardioid看上去可以直接用Spack整体编译,但,试了的都说sucks。似乎有的队一直卡在Spack上,其实直接不用Spack,手动编译就好了
  • Oracle的集群用的是Oracle Linux 7,based on REHL 7,也就是说和CentOS 7的环境差不多一样老。所以也出了C++ ABI的问题,好在临时抱佛脚了

比赛要求跑几十套参数,大概要换几种网格尺寸,精度,计算方法跑,总共要跑几十种组合。跑了一轮下来,发现某一类参数组合会炸,总结一下有几种爆炸的姿势。第一种炸法,用gdb Backtrace一查,哦就是文件权限没设对,低级错误。第二种炸法,算出了NaN。但仔细读instruction,发现出题人似乎早就预料到选手们能跑出NaN,因为有一个问题就在问”你们见过NaN了吗“之类的,那肯定就是出题人故意设的坑。年轻的队友看不懂人性的险恶,甚至萌生了改代码去修NaN的想法。第三种炸法,发现backtrace不出来,怀疑是栈炸了。先改了ulimit,无限栈空间,不行。单步调试到一个for循环读取数组,程序就异常了。我大脑一瘫,居然怀疑这个读取操作炸了栈(读取操作不会写入栈啊喂!),因为数组在高地址的堆里(0x7ff),离栈很近,说不定越界越到栈上了,甚至去算了base+size有没有大于esp的地址,结果是完全没事。继续debug,又遇到了一些匪夷所思的事情,比如不可复现的爆炸,第一次看到值异常,第二次就值正常了。我直接进行一个思考的放弃,1am了,到点睡觉了,day2还得通宵,于是就留这个守夜的队友就自己继续debug。

第一天晚上有三个在学校的队友守夜,主因是组委会完全无视50%队伍来自中国的事实,要求我们在12am-8am开摄像头供人围观(直播睡觉?)。跟Chair complain,

Kathleen> 你咋不早说

我还指望其他中国队会比我更早发现这个问题然后去argue,怎么只有我被喷了。Chair最后还在Warp up meeting还说,有些队伍不喜欢social只想去睡觉。(不会吧,不会吧,不会还有人打比赛还想睡觉吧。

洗完澡刚躺平的时候,那个队友就发消息说,de出来了,gdb不靠谱,还是printf大法好,最后查出来是integer overflow了。好家伙overflow和underflow都齐了,那肯定是出题的人故意的。这个overflow有一个tricky的workaround,让MPI跑在更多节点上就好了,因为会发生这个overflow的算式会除以节点数,节点数一搞大就不overflow了。八卡跑八进程,不能再多了?不存在的,一张卡跑两个MPI进程就完事了。(不过我估计还是栈烂了导致GDB行为诡异,说不定是RDMA把栈写坏了,因为这个overflow的结果似乎会propagate到MPI的参数)。

复现

搞复现的同学因为饱读各种AI paper就被我抓过来做这题,最初他以为现场赛的难点是在写paper上,因为之前在Azure上测试的时候一切都稳如老狗,虽然没时间测Oracle,但问题应该不大吧……吗?

真到了在Oracle上就,不得不说真是充满了惊喜(指新bug)。Oracle这边不像Azure,没有自带MVAPICH,只能自己用Spack编译一个,IB卡配置得也比较复杂,似乎是双口100G的RoCE,不像Azure是单口IB。程序似乎能正常编译运行下来,能跑出一些结果,只不过嘛……偶尔会在计算末期爆炸一下啦。根据我没几年的丰富经验,只要MPI程序能够跑出结果,问题就不是很大。一开始盲猜是运气问题,爆炸是随机的,重跑一次就好了。重跑了几次发现,是特定组合下的参数100%会炸,而且似乎是MPI的内部错误,挂在了同一个MPI函数上。由于程序总是在几十分钟后炸,用gdb调试几次可能一两个小时就没了,就打算先试各种民间偏方,同时先把能跑的点跑下来。

诡异的是,改无限栈空间,换MVAPICH的版本,使用Slurm,加MPI运行参数,都有时候能让程序跑起来,之后又失效了。也发现一些方法根本就没用,比如改编译MVAPICH的fabric参数,或者换HPCX MPI(然而自带的这玩意就没成功运行过)。从白天调到大半夜,程序一直处于能运行与不能运行的叠加态。Day2早上回到会议室,看得出那个队友被折磨了一晚上,身体已经完全被掏空了,大脑完全停止了思考。在我睡觉期间,队友去问了大好人Oracle的工程师Marcin,他给了一个写满了各种魔法MPI参数的博文, 然而这个魔法博文里提供了OpenMPI的参数,提供了Intel MPI的参数,提供了Platform MPI的参数,就是没有提供MVAPICH的,队友试着照着博文的参数复刻出一套MVAPICH的参数,然而并没有什么用。

Fun Fact:大好人Marcin在第二天晚上也帮我们试了一下MVAPICH,并给了一套参数,

1
mpirun -hosts hpc-node-1,hpc-node-2 -env MV2_IBA_HCA=mlx5_2 -env MV2_USE_RoCE=1 /nfs/cluster/osu-micro-benchmarks-5.8/mpi/one-sided/osu_get_latency

我队友除了没指明MV2_IBA_HCA以外,其他参数都是这么写的。(不过其实我怀疑加了MV2_IBA_HCA这个就好了,只不过到最后都没时间测)

于是,

Neko.d> 这个MPI大多数的时候能跑,少数时候会炸,说不定是MVAPICH的bug

Marcin> we can take a look and report to Dr. DK Panda.

古有简历直达boss直聘,现有bug report直达author。

到了第二天中午,debug还是没什么进展。我还是觉得好像也不是非得用MVAPICH才行,一看instruction没要求,应该可以换吧。问了其他队,好家伙,有的队打一开始就是拿OpenMPI跑的。于是准备换Intel MPI,这玩意久经考验。虽然说不定Intel MPI能以一己之力扭转程序的性能特征,改变性能曲线的trend,进而颠覆了原论文的结论,但继续卡在这个问题上也不是个办法。用Intel MPI + 自己编译的GCC 9重新编译ramBLe,第一次运行的时候不加MPI参数,程序直接就爆炸了,甚至连计算都还没开始。我还以为又凉了。抱着死马当活马医的心态,试了一下博文里的参数,程序居然能跑起来了!还成功的跑完了!还第一次看到Intel MPI不加奇奇怪怪的参数还跑不了的情况(一般我觉得加太多参数,叠太多buff会让程序炸得更惨)。

buff组合,只能说全是魔法,只有一点代码:

1
-iface ens800f0 -genv UCX_TLS rc,self,sm -genv UCX_NET_DEVICES mlx5_2:1 -genv I_MPI_FABRICS shm:ofi -genv I_MPI_FALLBACK 0

再次重跑之前不能跑的点,诶,能跑出结果了。然而这个时候,比赛时间不太够了,之前用MVAPICH跑的结果又不能用。为了赶上进度,队友还想着一个节点同时跑两个点,然而我这个学期的project就在研究co-located programs之间相互干扰的问题,所以这个想法被我毙掉了,反正大不了就把原来的MVAPICH的数据加个说明交上去凑数,不过其实最后绝大部分结果都赶上了。此外,还有绑核的问题,MVAPICH绑核默认会绑成一个非常奇怪的姿势,但instruction又没提绑核的事情,干脆让Intel MPI自由发挥,用默认绑核的顺序就完事了。最后与MVAPICH的结果相比较,绑核和换Intel MPI都没有造成太大的影响,trend还是一致的。

QE & 神秘应用

这两题都是要花钱跑的,作为一个常年抠门,特别是常年在云服务器上抠门的人(但其实我作为AWS的Intern烧掉了AWS不少钱),自然是不太舍得大手大脚的让QE和神秘应用在八CPU节点或者八卡上做测试的。抠门如我,给了他们一个有一张V100的Intel Haswell的节点,在这个便宜的节点上先测试好,再换到正式环境跑。虽然是Intel的CPU,但Haswell只支持到AVX2,它能跑的代码AMD平台应该也能跑。

其实这两个才是赛前我比较担心的应用,因为这两道题目在赛前就看上去还没有另外两题准备的充分的样子,特别是神秘应用的同学人在香港,只能线上沟通,但结果是,这两道题反而没有遇到太多问题(或者说队友靠自己就闷声把问题修好了),出乎我的意料。QE的同学先开始说CPU版的单元测试跑不过,修了一下,好像是缺了什么库之类的,过了没多久,就说CPU的单元测试跑通了。开始叠优化选项,CPU版的单元测试又跑不过了,他自己鼓捣一下,又能跑过了。之后又开始折腾GPU版,这次遇到问题总算棘手了那么一点,这个问题让他修到了第二天。保险起见,就让他在Day 1到Day 2的半夜用四个节点把保底的结果跑出来,然后去思考用什么机器能刷高分数,跑完benchmarks有闲钱了就去刷高分数(然而最后是有闲钱但没时间了)。如果GPU版本能跑了,可以考虑明天和神秘应用一起时分复用GPU节点。为了省钱,还不让他开八节点来跑(不过仔细一想,其实好像花不了几个钱,但应该能提高不少分数)。

神秘应用那边,Day 1,他上来就列好了用来编译安装程序的所有的命令(他是怎么把命令列的这么全的?他能预知未来?)我看了两眼,给他补充了一些东西,他就自己去折腾了。我预期他会出现各种各样的状况,然而他安静得就像跑路了一样,之间就问过一次MPI相关的(HPCX又跑不起来,换MPI重新编译就好了),Python软件包缺失,NVCC和MPI的环境变量问题,吓得我以为他跑不出来就开始摆烂了。到了Day 2,他遇到了只有在多卡节点上才能测试的东西,给他开了A100节点后没多久,他下一句话就是,

Neko.d> 应该可以连进去(八卡节点)了 @12:25

队友> 现在应该是跑完了 @14:48

这顺利的就离谱。想到跑多节点可能会各种出锅,需要花不少时间用两个GPU节点debug,加上我对我多机多GPU的debug经验和速度都不太有自信,不如把钱省下来给benchmark。神秘应用在A100上跑的时候,QE的GPU版似乎还是不太行的样子。

所有的task在八卡单节点都搞定了。

SC21 Phase 3:演你们!

跑benchmarks的老哥人在英国,大概是Day 2中午的时候终于想起来要上号了,此前训练的时候,

队友> 现在是在训练还是比赛啊?

看起来中国到英国网络不通。

跑IO500不烧钱,他就先跑这个玩玩。起初我们还对CycleCloud自带的分布式BeeGFS抱有期望,先跑了一个五节点的分。第一次,8分,不知道是什么水平,只知道是T队去年的10%不到的分数。虽然对这届IO500来说,我们直接进行一个烂的摆才是最优策略,浪费时间提升10分,在某些打榜专用FS面前,跟没有提升没有区别,但交个8分似乎也太丢人了。又跑了一下单节点的,10分。好家伙,上了分布式还负优化了(大概是通信的锅?或者集群配置有问题?)

跑完IO500热热身,他就……去睡觉了。他那边已经是当地时间的早上了,他再次上号的时候已经10个小时过去了,我们这边已经是Day 2的晚上了,看起来他还挺自信的,睡觉睡得很踏实。

QE和神秘应用跑的非常的经济,愣是省了1k多刀给benchmarks烧。我们的原本想到了A100根本开不出来的情况,就准备退而求其次开V100,然后发现了…V100也开不出来。(估计是T队此时也在拿V100跑benchmark)。好不容易开出两台V100,又发现坑爹Azure的Image里,有IB驱动,但只有完全用不了的IB驱动。Image里只带了支持新网卡的驱动,但机器上只有旧网卡,赛前根本就没试过V100节点的我们防不胜防,想不到还有这种事(然而队友aka前运维去年也是用的V100节点,咋啥都不记得了)。总之,如果硬要用V100节点,我们只能准备手动装OFED。(然而T队后来说他们早在测试的时候就发现了这个问题,估计自动化脚本都写好了)

然而,我从来没见过队友用过clusterssh和其他能broadcast input的terminal,对他自称能在短时间内给10+台节点配好OFED的说法深感怀疑。而且我自己装OFED的时候遇到过升级Linux内核的同时把GPU内核模块整没了的情况,说不定好不容易配好了OFED了,CUDA又坏了,所以不是很放心让他继续把时间花在V100上。

折腾V100的期间,ShanghaiTech的运维问我们要不要接盘他们的两台A100,他们准备释放了,但我那个时候还不知道IB驱动的坑,就没接盘。等到发现IB驱动的坑的时候,我只有非常的后悔,不过我又发现我顺手一开就开出两台A100,就是排了大半天的队。感觉V100那边跑不出来了,干脆不如能开出几台A100就跑几台。算了一下钱,发现,

Neko.d> 出现了有钱花不出去的问题

我们有足够的钱等A100开出来,哪怕最后开出了8台A100,我们的钱也不一定能花的完。并且我大胆假定,大部分的队伍会在比赛末期因为经费不够把A100让出来(后来发现,还得感谢某些搞事情的队高抬贵手,没有跑去抢A100),于是我就让队友一边在A100集群上调参一边等机子。从第三台机子开始,Azure开始0连排队都不让排了,但只要多试几次就能排上队,平均下来进入排队的状态要花10分钟,排队再花10分钟,也就是说20分钟能开出一个节点。反正大家的进度整体良好,没有我运维什么事,我就去当一个没有感情的点鼠标机器好了。

本来想写个脚本自动轮询,发现公司给的Mac不让Chrome访问不安全的网站(CycleCloud Web Console的HTTPS的证书没配好),用不了开发者工具来生成模拟请求的curl命令,所以只能人工点鼠标了。

用了差不多两个小时,总算开出了6台A100节点,但从此再也排不上队了。虽然我觉得没有哪个队钱多到占着A100到最后一秒(然而真的有这种队),但之后真的就一台也开不出来了。

队友那边,他掏出了不知道哪来的祖传HPL和HPCG二进制文件,复制粘贴,执行含有祖传参数的祖传脚本(怕不是ASC那会用的)就开始跑分了!现在Linux的二进制兼容性这么好了吗?不过6节点HPL一开始只能跑出100T左右的成绩,用htop看CPU占用,红红一大片,非常的不对劲。结果就是MPI进程/线程数设置得不对而已,经典Context Switch了。改了改参数,跑分期间看到了不错的预测结果,但居然跑炸了。队友突发奇想,改低了线程数,好了,太怪了。(某队还碰到了非常神奇的Verification failed,开眼界了)

队友自称在校内集群跑HPL的时候成功的把节点直接跑崩,这里没把Azure的物理机跑崩真是谢天谢地了。

后面的故事就比较简单了,48张A100加持下,钱到位了,金钱的力量绝不让人失望。狗贼T队先扔了一个很低的HPL分卖弱,到比赛快结束的时候,终于把真正的成绩放出来了,HPL,HPCG,IO500全部领先当时榜一一大截,仿佛SC20重演。看了一眼我们刚跑出来的分数,那没事了,就让T队开心那么几十分钟吧,然后再让他们感受资本主义的险恶(大雾)。

抖S的队友总觉得没有榨干A100的性能,从理论性能上看,HPL还是有希望跑上300T的,可惜到了最后几分钟也只跑到了284T。但我脑子一抽,居然同意了让他们在最后几秒用这个成绩override掉原来提交的280T的成绩,差点SC20重演,这是这一次比赛距离翻车最近的一次。还好负责提交的同学足够聪明,是先提交再删除,不是先删除再提交。结果是在ddl前提交成功了,但来不及删掉已经提交的成绩了,要是这个update的顺序反了就emmm。但赛方Grafana还是傻掉了,不能处理多份成绩的样子,显示不出我们的HPL成绩,于是我们创造了SC21最高LINPACK分高达0 GFLOPS的奇迹!(大雾)

另外,IO500原先是跑出了10分的“好”成绩,但忘了保存了。再跑单节点的时候又只有8分了,队友直到最后一刻都还想装Lustre来刷高IO500,但就算分数高了一点,也并没有什么*用。

SC21 Phase 3.5:Interview

去年需要我们在最后做一个完整的答辩,今年就变成了Poster+各赛题单独interview。Poster答辩前我还在吹水,完全没有意识到Poster答辩还占分,结果iPad(用来在比赛期间挂着线上会议)突然冒出来一句声音让我答辩,我《完全没有任何准备》(自豪),自然是讲得稀烂,我甚至都不记得我做的Poster里写了啥,只能对着评委说,

Neko.d> 嗯嗯你们自己看看吧,反正这个也不是最终比赛的配置,看看就好

结果发现最后Poster分并不高(我紫菜)。

其他队友的分赛题Interview比我靠谱多了,基本上问题都答得上来(你们是什么时候知道这些赛题的物理背景的?)。特别的是,负责Cardioid的的大二队友不太能说英语,但在我们另一个队友,托福100+的大师的协助下,加上interviewer照顾我们把问题打在了聊天框里,这场interview就在

  • 我听不懂Cardioid队友跟翻译说了什么
  • 我听不懂翻译跟interviewer说了什么

的情况下完成了。我只知道

  • 评委很满意我们的回答
  • 他们笑得很开心,但我不知道他们在笑什么
  • 评委问:“假如你患了绝症,你愿意用我的模拟器造的心脏吗?”
    • 回答:”去tm的simulation,我直接成为赛博人,肉体是不需要的“

Ending

其实这1w字的流水账早就在10月的时候写完了,只不过拖到了第二年才发出来,欸嘿。说起来这也是我最后一次以正式队员/队长的身份打SC比赛了,想想好气啊,因为这破疫情,痛失2x美帝 2x新加坡 2x北京 1x厦门免费旅游机会,没能帮学校花钱,我感到非常的愧疚。果然还是想续一续我的学生身份,继续努力的帮学校花钱。希望今年能以Year 0 PhD Student的身份打ASC22(offer不会下不来了吧),然后在未来某一年以Presenter的身份回到SC的会场,并成为目击证人,亲眼见证在nike的successor在SC SCC把其他队锤爆的那一刻。