朝(大学初)花夕(临近毕业的反思)拾

我不是一个爱回忆的人,但是总觉得过去22年是我作为男生部分的时间,总应该有点什么东西留下来,正如鲁迅的《朝花夕拾》是对旧文化,养育他的之乎者也中汲取新世界白话的力量。我所认为的新时代,一个没有强权,网络绝对自由,有能力者自食其力的世界也会在我所创立的公司中体现。Anyway,show time。

四年的时间,我其实只是想做更有趣的事情,没想到把吉他、摄影、无人机甚至女友义无反顾的丢掉,在一个PUA国度里面,我活的好压抑。我觉得整个大学的失败是我一手造就的,没有找到最需要发力的主要矛盾。每次想的太快做的太慢。

我从一开始就是想make GeekPie_HPC great again,其他所有的都是为了学更多的东西。博士是Jump Trading实习结束以后决定的,因为赚钱全是engineer effort,对我没什么挑战。大致真正发现这个学校的丑恶也是每一次面对这个学校的老师的时候,我觉得我太天真、太傻了。

试错与探寻兴趣所在

约莫着大一的时候,发现《数学分析》时间和精力上都比不过卷王,第一学期就拿了B+,貌似 Competitive Programming 也不是我的菜,张龙文在 ICPC和智能体已经拿了银牌和第四了,由于反编译助教发的标程(连debuginfo都没去),直接交了 asm(""); 导致在 MOSS 里控制流和别人一样(没学编译原理,完全不会AST,这题Foo 出的,一半人被抄袭。),后来confess 拿了 CS100 的 B,物理花了很多时间,拿了个A。前几个学期做 pre 的课都很好,没项目就考试的我就不想花时间去砸时间刷题。

第二学期的失败在没有朋友和没有有效获得老师和助教的信息。电路和离散都没拿到好分,重要问题是离散在某一次作业之后助教在 piazza 的很隐蔽的地方发了下一次不能再在 gradescope 上不 assign page,然后那一个月的作业都零分。个人感觉我离散学的还挺好的,后来曼哈顿距离、博弈树实习的时候还给别人做pre。电路作业挺难的,但每次解微分方程的时候都敲错计算器,高中的遗留问题吧,考的不好,作业也没对答案。其他几门课还不错,《数学分析2》拿了 A-,期末考试就考了格林定理的特殊情况,也是当时看的stein的《傅立叶分析》、《复分析》、《实分析》。哦,思修提示重教作业在我在印度旅游手机丢的情况下,微信收不到消息,因为被清空了,后来argue的时候,说我违反规定在暑假初出去玩,如果继续argue失败会被勒令“社死”(通报批评+退学)。后来还是选择了挂科重修。说来也有意思,思修的影片还是我剪的,我队友也没其他途径提醒我。第二学期成功的地方是结识了张龙文、叶者、张弛斌。三个很厉害的人,至少比我当时厉害多了。当然也结识了诸如csh之流。出去打了hackathon和ctf,成绩还不错,全靠被带。

暑假先去了新马泰印尼。暑学期搞了个fintech课,完善了hackathon的东西拿了第一。那次用奖金吃饭的感觉就很好,同时我学到了如何和女同事合作。

社会实践没啥好玩的,别人都脱单了。
IMG_1621

IMG_1636

暑假后面学校里还有个讲precedure decison的课。

暑假的后半部分就在帮zhaozhe学长跑实验,是一个AI Adv的活儿,缺很多实验。主要我做的部分实验都在那个暑假搞定了,后来Foo又给了个和叶者一起合作的锅,那我也接了,只是第二学期的Compiler和OS太花时间了。所以很多事情暂时搁置了,但是我在Foo组每周听到的组会上的内容真的对我的提升很大,当时讲SGX和Side-Channel的很多,我也有了个在谢学长对面的座位,这让我更好的向学长请教。对AI Sec上基本就是调包,改一个类似fuzzer的mutator生成器,让数据的AUROC比baseline好。叶者的锅就一直gu一直gu,主要他写的太杂了。Z3 SMT-based验证一个stackful的语言不是那么难,问题是,很多内部的东西,比如spec,文档都不全。而且1.2一直在更新,每一个小版本都会改动很多。

第三学期,Compiler被龙哥带了!

编译原理后半部分是他写的,101不会的题目都请教他,有道维护区间有序的题用list没用dynamic vector,查找O(n)没过一个点。不过这助教简直傻逼,洛谷原题不改。OS教的很差,OSPP写的很好,但是就是教的差,lock guard讲了3节课,CA上过的东西狂上,页表怎么切讲得不清楚,后面我去上课就复习Compiler了。Compiler我上的还行,Foo后期讲了IFDS一些数据流静态分析和他组会上经常会提到的污点分析是我那时候常干的事情,我们的编译原理project也是用了TaintART的DTA,在所有的syscall和敏感API调用上动态的给开发者返回possible emission信息,东西是在java maple IR上做的,其实就写了个描述层。到最后很多东西没解决,就糊了一个demo。(面向testcase编程。)其中国内考试的时候去了一趟深圳TSBI,是我唯一一次出去开会,见到了Petter Davison、中科院计算所的大佬们,还有jyy riscv nemu课设、杜东penglai、中国chisel之父刘jiuyan。总之就是去社交了一波。OS是没时间了交了个改了一点点的project3上去没混淆。就没了。概率论这学期必修是和别人错开的,因为和OS冲突。不过zcb也是这学期选的,他101上学年就学了。也是一个精致的利己主义。

第四学期开始的时候搞的GeekGame2020,用React糊了一个前端,比叶者这个专业的还是差了好多好多。第四学期被他带了一半。CA的前半部份上的贼差,后半部分上的很好,尤其是spectre、RAID那里,我也 CA的后半部分project主要是他写的,lab 除了 map reduce是我做的。选了RL、CG和Parallel Compuing。RL和CG靠带。Project是和他一起写的。PC全自己写的,尤其是cuda,主要原因是夏而下要打ASC、SC了。直接赶驴上马。本来想做一石二鸟的工作把QuEST优化很多的,改了个MPI版GPU,性能基本线性叠加,但问题是这没卵用。连决赛都没进,但是后继无人导致我还是成为了队长,搞了wiki开始训练的pipeline。龙哥gu了这超算比赛和之后的龙芯杯和Compiler比赛,去yu组赚钱去了。叶者也去那里赚钱去了,不过Mars给的确实有点多。我太菜了,没去。之后就去Jump Trading了。

这个暑假可以说是终身难忘。众所周知我的两个舍友在第一学期就被CS100劝退转专业了,又是天天在寝室吃麻辣烫、打游戏的人,我很受不了,但是不能换寝室,因为有人不愿意。但是Jump Trading 给我31楼的昌邑路海客滨江一套。以便开展我的🧍‍♀️活动。同时我感受到了被尊重的感觉,以及我饿技术可以被马上应用于production。比如刚学的parallel computing就用上了。以及"谈笑有清北",那时候身边交流的都是清北/CMU大佬,让我觉得,所有的技术问题,我都可以解决的感觉。

但事实是,出了Jump Trading就没那个机会了。没有人能记住一个垃圾学校的垃圾。第五学期干的事是上研究生课,尤其是CA2、CA3、OS重修、概率论、网络、数据库、计算理论还有个SC20一起搞的时候,我觉得我不care GPA了,因为我受够了这个学校的PUA、我只要知识、和锻炼我在压力下的水平。我感觉CA2太需要花没有意义的时间了,Sniper连多线程同步都没写好,及其浪费时间,考试的时候让你手推不同周期在干啥。

寒假做了6.824和看了6.888.

第六学期,学习到了在一个组里面怎么活。我觉得王老师是一个严厉的老师,这很好,但是他严厉的地方不对。在他实验室三个月的时间里,每周我都有他拍脑袋的任务,现在看确实是新发的ASPLOS22 PM相关关注的问题。可是搞清楚又有什么用呢,让我做的东西,实现也拍脑袋,我反正是做不出来,Meltdown我都没怎么实现过。这学期又学到了怎么当一个助教,感觉在上科大当助教吃力不讨好。被陈濛骂我出题他觉得没定义清楚就在那里闹。然后他讨论课从来不来。我也不知道该怎么搞。我感觉,还是不要自己出题吧。让他能找到原题比较好,否则他就觉得难了。哎,上科大不是北大。

暑假去暑研了。这是个15个人暑研的地方,我和北大的一位同学选了investigate order dependent tests,这是个Darko和Wing顾不过来的方向,因为他们本身有3篇要在暑假投出去的工作,还有Ruixin的Python flaky test Workshop,感觉在周会上一直很活跃的是修Flaky Test的chen yang 同学(她去UIUC了),但是修bug真的挺好费时间的,她一定很痛苦。我的话就一直在用Pradet跑artifact,需要给她提供order dependent变量,然后Darko总能找到class 的flakiness的案例,我们总能找到Pradet的bug,但是跑的3000+个case(对,iDFlaky+Non-idempedent+poluter的总共这么多,不过有些重复,有些不是OD。有问题都会去找Pu Yi,他是北大的,之前在做JPF,后来也在做JPF。总之就很怪,我们选的也是探索性的项目,等ICSE截稿了以后,Wing度假了2周后找我们实现一个bramble上的brittle test 改 flaky order test准备投ICST。传播方程写好了。可是bramble 完全不会debug,加之投稿来不及了,就鸽了,真的不太会mvn插件啊,反正推荐信是够了,北大同学在熊英飞组跑试验投OOPSLA也溜了。相反chenyang和ruixin做了python flaky test发了个demo。(感觉虽然学会了很多理论、DTA怎么传播,怎么找OD,但是没有学到idea,做的事情也是很糙。(不过,软工确实好发啊)总之,两次科研经历,如果老板能多给点指导时间就好了,否则兴趣都转移了。也可能我在本科阶段做的事比较功利。

第七学期就上了门创管的课,只有后八周,这是学分要求的最后的课,投资学与金融市场。讲的很理论,也是金融专业必修,也就是和这个专业的人竞争GPA。project糊了很多,比如chisel3 简易riscv单发射5级流水,chocopy,一个rust版cmudb,被cjj带着写badfs。比赛拿了第二。毕业论文是hdf5语义下放,是小圆ATC22 under revision文章的中文版+若干没放上去的实验。

对于Ph.D.的面试我还是有些东西想讨论的。不同老师的风格真的不一样,GaTech有两位面我,一位是做meltdown的🇮🇱人Genkins,我大概先说了对MDS的兴趣来自jump的intel processor micro benchmark,后面说了之后的一些精力,他觉得我的尝试都很没有想好,和大佬说话就不是拍脑袋了,很有engineer implementation价值。 他就认为他的任务是crack widely used stuff down. 他对于防御也没有兴趣,同时他对我的用高级的工具去解决前人就能做的东西很不齿,比如eBPF侦测内核,估计是我的思考他觉得没有意义挂了我。第二位是kim,做rustra的。开始也是问项目,问了threadsantinizer的实现,false negative怎么出现。有没有更完美的解决方案。我知道实现,create thread的时候把所有variable record 一下,每个path都DTA一下。fn就受ipc污染过的变量修改后检测不出来,函数order检测不出来。修补嘛,就说rust里send sync的方法。其他检查unsafe里变量有没有data race。(糊了一遍他的论文,幸好看过)不过似乎他觉得我回答不满意,也没要我。purdue最奇怪,poi陶瓷的时候很热情给了个面试过了下cv,之后王建国和我说poi招满了,艹。王建国老海王pua了,在邮件里面说他已经有USTC的优秀同学,还发了篇十四五计划 db规划,想着一定是北大/复旦没写过db的文科研究生翻译的,我寻思着什么垃圾dber,5年才3篇vldb,算了👋🏻。西北xingxinyu的面试极其不formal,说是代表committee,微信电话,全问的私活,想着也是看我有jt的经历,追着问我thread interleaving怎么debug,我就说了thread里差sleep,用script卡thread时间,停在thread里就好。他觉得不是one for all 的解决方案。cmu ece的面试也是走个过场,很不尊重我。

最后这一年我的想法是给Ph.D.做一个缓冲的一年,代码在学,因为博士还是新硬件体系结构、LLVM、kernel。所以还是把之前的几个项目都完善下。又做了助教/家教好累啊,出题还要想。

减法、加法

摄影的数据流向

由于NAS被肢解了,我前几年拍的照片都已经被删除了,我归因于在学校里根本没有好的数据解决方案,放个nas太容易断电断网,出了学校,由于学校出口教育网/电信网的分流问题,网络延时又特别高。自从全心全意只写代码以后,就再也没摄影了,不过最近有在捡起来。之前录的一些吉他曲也整理出来了,以后可以放博客上。现在博客在psychz tokyo上。

接管无人机社

我当时拉了5个人,一个西南工业大学的学姐,家琪是 SLAM 大师,还有物理学马大师,和贺贯奇,买了一堆飞机,飞了几乎所有类型的飞机,CADC去玩过一次。现在是陈大师管理了。

女装与MtF

我从印度回来以后对自己进行非常深刻的思考,我觉得我需要一个时机来让我有理由干这件事,我在Jump Trading实习的时候由于有自己的地方,我天天在晚上穿女装,感觉很爽。发现自己真的喜欢以女性的方式去社交。其实我早就知道HRT。但是付诸实践真的是因为我觉得这个世界对男人过于残酷,我很害怕。我只是个喜欢和强者交朋友的xyn,请多指教。反思了一下,我每天观看twitter的时间有点过多了,得少关注美美的人,多关注自己的码力。但是这是xyn的后遗症吧,我的青春又还有多久呢?

YOLO


我很喜欢的一种精神,也是和NTU的shenghao聊天的时候知道的。我为了ISC21能有名次把抽代给挂了,其实我多学半周应该B不是问题,Daniel觉得我是态度问题。毕竟最后的OH也没找他。后来知道他学期末发了那篇PDE拿tenure了,恭喜🎉。所以挂了,不过凸优化我还是好好复习了一晚上混了个B+。yolo我认为是你可以为了自己想要的放弃掉世俗意义上的别人要你做的事情,这很重要。

可以托付终身的人与物

我的准老婆,从高三的时候就认识了。之前一直情绪不稳定,我也一度因为自己太忙的原因抛弃过她,但是我知道她很爱我,我也很爱她。希望我能把我的未来的一切喜怒哀乐、功过是非都托付给她。已见她父亲,已被透,已半同居。结婚还需要一年。回上海定居还有8年。

人生可解与不可解

我无法知道从进大学以来的一切发生的事情,我曾经认为,我能用自己的能力发很多paper、以满绩完成最难的课程。总有人卷没有意义的东西,也总有人用旁门左道过桥。但是我会选择一条我认为离改变世界最近的一条路。我选择UCSC,(当然也没得选)我想在搞paper的同时见识下什么是硅谷精神。人生是Undeciable 的,也同时是 Deciable的。

The measurement of TSO on M1 Max

We've seen that there's already a TSO Enabler for M1 and worked perfectly fine on M1 Max using kernel injection kmutil trigger-panic-medic --volume-root /Volumes/Data/Library/Extensions/TSOEnabler.kext just like Hackintosh.

So, I just want to check the famous OOTA problem on both TSO on and off.

Line 24 will be stuck without TSO and will work fine with TSO.

SC23 Attendency

这次是带学弟们打比赛,4090快递小哥,运费自己掏,顺便问问cxl科研的人在干嘛。现实是很多组都已经拿到样品了,但是有很多bug

IA3 https://hpc.pnl.gov/IA3

Micro的见过很多次的头在讲gapbs怎么用PIM paradigm优化。gapbs workload。很像pnnl的推介会。

offload operator to PIM。

General view for SCC ShanghaiTech

基本都是坏的,电脑还是挺容易坏如果你不交钱。

沙特甜枣

SW/HW codesign for ML

SW/HW has great progress, especially offloading the operator into the ML, the insight is the inference could be approximated to fp4 even and all the operator is read only.

HPC Checkpoint Restore

MPI integration, they want offloading through DPU and compliant to checkpoint of data and Linux control flow. Add Debugagablity to MPI.

Parallel IO

SK Hynix Booth

CXL Booth

Chip inspection

ICON spack compile

# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

# ----------------------------------------------------------------------------
# If you submit this package back to Spack as a pull request,
# please first remove this boilerplate and all FIXME comments.
#
# This is a template package file for Spack.  We've put "FIXME"
# next to all the things you'll want to change. Once you've handled
# them, you can save this file and test your package like this:
#
#     spack install icon
#
# You can edit this file again by typing:
#
#     spack edit icon
#
# See the Spack documentation for more information on packaging.
# ----------------------------------------------------------------------------

from spack import *
import os

class Icon(AutotoolsPackage):
    """ISC22 ICON package."""

    homepage = "https://hpcadvisorycouncil.atlassian.net/wiki/spaces/HPCWORKS/pages/2792161313/Getting+started+with+ICON+for+ISC22+SCC"
    url      = "http://localhost:31415/icon-2.6.4.tar.gz"

    maintainers = ['spedoske','victoryang00']

    version('2.6.4', sha256='1860028836d0894224ce301c3d0cb27a899548823267b08bf5c97ae696c3758d')

    depends_on('libxml2')
    depends_on('eccodes')
    depends_on('intel-oneapi-mkl')
    #if self.compiler.name == 'nvhpc':
    #depends_on('intel-oneapi-mpi')
    depends_on('netcdf-fortran')
    depends_on('netcdf-c')
    depends_on('hdf5+mpi+fortran+hl+szip')
    depends_on('zlib')
    depends_on('libszip')
    depends_on('mpi')
    depends_on('cuda')
    #depends_on('nvhpc')
    depends_on('serialbox')

    def configure_args(self):
        args = [#'--enable-art',
                '--enable-coupling',
                '--enable-serialization',
                '--enable-emvorado',
                '--enable-grib2',
                '--disable-yaxt',
                '--enable-sct',
                '--enable-ecrad',
                '--enable-rte-rrtmgp',
                '--enable-mpi',
                '--enable-gpu',
                '--disable-explicit-fpp'
                ]

        # if self.compiler.name == 'nvhpc':
        #    args.append('--enable-gpu')
        # else:
        #    args.append('--disable-gpu')

        #from print import pprint
        #pprint(vars(self.spec['nvhpc']),depth=4)

        #print(os.environ)

        os.environ['CC'] =  os.environ['MPICC']
        os.environ['CXX'] = os.environ['MPICXX']
        os.environ['F77'] = os.environ['MPIF77']
        os.environ['F90'] = os.environ['MPIF90']
        os.environ['FC'] =  os.environ['MPIF90']


        os.environ['MPICH_CC'] =  os.environ['MPICC']
        os.environ['MPICH_CXX'] = os.environ['MPICXX']
        os.environ['MPICH_F77'] = os.environ['MPIF77']
        os.environ['MPICH_F90'] = os.environ['MPIF90']
        os.environ['MPICH_FC'] =  os.environ['MPIF90']

        #nvhpc_bin = '/home/coffee/spack/opt/spack/linux-ubuntu20.04-zen2/oneapi-2021.4.0/nvhpc-21.9-ymnvxvr4e2q7475djr4lig7cbucg54uv/Linux_x86_64/21.9/compilers/bin'

        #os.environ['OMPI_CC'] =  os.path.join(nvhpc_bin,'nvc')
        #os.environ['OMPI_CXX'] = os.path.join(nvhpc_bin,'nvc++')
        #os.environ['OMPI_F77'] = os.path.join(nvhpc_bin,'nvfortran')
        #os.environ['OMPI_FC'] =  os.path.join(nvhpc_bin,'nvfortran')


        CPPFLAGS=["CPPFLAGS="]
        FCFLAGS=["FCFLAGS="]
        LDFLAGS=["LDFLAGS="]
        LIBS=["LIBS="]

        # zlib
        LDFLAGS.append('-L{}'.format(os.path.join(self.spec['zlib'].prefix,'lib')))
        LIBS.append('-lz')

        # hdf5
        CPPFLAGS.append('-I{}'.format(os.path.join(self.spec['hdf5'].prefix,'include')))
        FCFLAGS.append('-I{}'.format(os.path.join(self.spec['hdf5'].prefix,'include')))
        LDFLAGS.append('-L{}'.format(os.path.join(self.spec['hdf5'].prefix,'lib')))
        LIBS.append('-lhdf5hl_fortran -lhdf5_fortran -lhdf5')


        # netcdf-fortran
        FCFLAGS.append('-I{}'.format(os.path.join(self.spec['netcdf-fortran'].prefix,'include')))
        LDFLAGS.append('-L{}'.format(os.path.join(self.spec['netcdf-fortran'].prefix,'lib')))
        LIBS.append('-lnetcdff')

        # netcdf-c
        CPPFLAGS.append('-I{}'.format(os.path.join(self.spec['netcdf-c'].prefix,'include')))
        LDFLAGS.append('-L{}'.format(os.path.join(self.spec['netcdf-c'].prefix,'lib')))
        LIBS.append('-lnetcdf')

        # blas and lapack
        CPPFLAGS.append('-I{}'.format(os.path.join(self.spec['intel-oneapi-mkl'].prefix,'include')))
        LIBS.append('-lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm -ldl -lmpi -lxml2')

        # xml2
        CPPFLAGS.append('-I{}'.format(os.path.join(self.spec['libxml2'].prefix,'include/libxml2/')))

        # eccodes c/fc
        CPPFLAGS.append('-I{}'.format(os.path.join(self.spec['eccodes'].prefix,'include')))
        LDFLAGS.append('-L{}'.format(os.path.join(self.spec['eccodes'].prefix,'lib')))
        FCFLAGS.append('-I{}'.format(os.path.join(self.spec['eccodes'].prefix,'include')))
        LIBS.append('-leccodes -leccodes_f90')

        # serialbox
        LDFLAGS.append('-L{}'.format(os.path.join(self.spec['serialbox'].prefix,'lib')))
        FCFLAGS.append('-I{}'.format(os.path.join(self.spec['serialbox'].prefix,'include')))
        LIBS.append('-lSerialboxFortran')


        # LDFLAGS.append('-L{}'.format(os.path.join(self.spec['cuda'].prefix,'lib64')))
        # LIBS.append('-lcudart')

        # gpu
        #LDFLAGS.append('-L/usr/lib')
        #LIBS.append('-lstdc++ -lstdc++ -L/usr/lib')

        # gpu
        if self.compiler.name == 'nvhpc':
           LDFLAGS.append('-L{}'.format(os.path.join(self.spec['cuda'].prefix,'lib64')))
           LDFLAGS.append('-L/lib/x86_64-linux-gnu/ -lstdc++')
           LDFLAGS.append('-I{}'.format(os.path.join(self.spec['openmpi'].prefix,'lib')))
           FCFLAGS.append('-I{}'.format(os.path.join(self.spec['openmpi'].prefix,'lib')))
           LIBS.append('-lcudart')

        args.append(' '.join(CPPFLAGS))
        args.append(' '.join(FCFLAGS))
        args.append(' '.join(LDFLAGS))
        args.append(' '.join(LIBS))
        args.append('SB2PP='+self.spec['serialbox'].prefix+'/python/pp_ser/pp_ser.py')
        if self.compiler.name == 'nvhpc':
            depends_on('nvhpc')
            #args.append('MPI_LAUNCH='+self.spec['openmpi'].prefix+'/bin/mpirun')
            args.append("MPI_LAUNCH=/usr/bin/mpirun")
            args.append('NVCC=nvcc -std=c++11  -ccbin {} -allow-unsupported-compiler'.format(self.compiler.cxx))
        else:
            depends_on('intel-oneapi-mpi')
            args.append('MPI_LAUNCH='+self.spec['intel-oneapi-mpi'].prefix+'/mpi/2021.4.0/bin/mpirun')
            args.append('NVCC=nvcc -std=c++11  -ccbin {} -allow-unsupported-compiler'.format(self.compiler.cc))
        return args

    def setup_run_environment(self, env):
        env.set('PYTHONPATH', join_path(self.spec['serialbox'].prefix,'python'))

M1 Max 提货体验

花了半个月,11月23号早上就到货了,本来是一个月才到货,这也是一个小惊喜吧。买这个本的初步想法就是学习arm汇编,同时尝试反编译一下metal api到苹果的asic的过程。总之就是想花钱买开心。

21637743555_.pic_hd

LLVM all 14分钟就编译完了。几乎是我9700k的2倍。我终于实现了rust电量自由。

SC21 失败回顾

在北京时间11/16日早上9点半至11/18日早上7点半超算队线上参加了SC21-SCC,这是本年的最后一战,我是按照我的最后一次比赛的标准来准备的,毕竟有申请和科研,之后也不会这么好玩的参与比赛了,以后可能为了智商保持参加一下ctf。在准备和规划上和比赛进行时有挺多出入的,所以只能说我带领的同学很好的各司其职,失败的原因我更愿意归咎于我的Timing的能力。不过我也明智在多找了几个运维高手。

赛题

预算是开始时给出的,在Azure上只有1500USD,在另一个今年新加的Oracle机器上不限,下面标*的是在oracle上跑的题目。 SC21的题目很早就放在网上了,大概有

  • Benchmark(10)
    • HPL (3.5)
    • HPCG (3.5)
    • IO500 (3)
  • Application
    • QE (20)
    • mystery (15)
    • Cardioid (20)*
    • Repro (25)*
  • Poster (10)
    面试包含在各个题目的评分中了。这是我们最后的成绩

poster比清华低1.*分,benchmark低4分,QE高2分,mystery低2分,最后低了5分左右。而benchmark和mystery都是卡的竞争导致的差距,也可以说是我们学生临场发挥的能力略逊于清华。

关于线上比赛的测试与准备

proposal乱糊

千万不要以为proposal就是全部,毕竟当时还不知道多少预算,我们就大概糊了一个什么时候跑啥的tactic。我们预想着是第二天凌晨的时候开始benchmark,这对我的指挥失误有些影响,那时候根本抢不到A100. 同时我们在比赛开始前就注意到标*的是接近免费的机器,只是到比赛的时候才知道才0.0021USD每小时,主办方确认能用,我们一早就把所有这种以v5结尾的测试机器先拿了,quota到限制了,别人就完全拿不到了。

我们claim说我们能完成spack integration,比赛前也确实完成了,我们给所有azure机器加了一个启动脚本用于给我们自己的slack发脚本,这最终导致我们免费slack消息超出10K条(以后得找学校赞助了。)

Azure搞笑后台

cycle cloud 之所以别人玩不来是因为有很多坑,而我们有王凯留(运维最省钱了)。他精通powershell,ruby。普通的image只能得到chef error等问题,大概只有北大和暨南使用的centos7可以过,但进去还是会有坑。在确定使用microsoft-dsvm:ubuntu-hpc:2004:latest这个能自动装好所有我们想要的东西(spack,go,rust)的基础上,他用cloud-init干了自动配置他自己编译的slurm,把他的--noswtich=0以及--shutdown=none还有cyclecloud.so编译进去。后来通过反编译他的那个.so只干了指定参数的作用。主要的流程,比如更新slurm机器状态都是jetpack做的。BeeGFS他后来编译了一个5.x内核可用的template,最后也上production了。最最重要的是,他在处理chef问题的过程中找到了cyclecloud如何确定整个区域谁拿走了什么机器的API,他之后用此写了很多脚本。还有更令人搞笑的事情,为什么azure cyclecloud 会用chef?因为巨硬收购了一家cyclecomputing的公司先一步踏入云超算市场,可是infra都还是之前那个公司的legacy开发。总之oracle现在上来了,巨硬现在要重新用ansible写一遍了吧,如果微软日本员工看到了,一定要招王凯留帮你们写infra筽,一个启动时两个apt相互抢锁PR如下一个chef安装时只用rpm的so覆盖deb的脏做法PR如下

RamBLe

总之同学们都写好脚本了,都开源了,大概就花了几天时间搞定的事情,比赛时就不用操心了,不过那几个队员做完题目也没能力再帮别人了,这也是人员上没清华有弹性的原因.不过我们这题做的好,和THU差不多吧。

Cardioid & QE

这次我主要负责QE,QE总之我们是研究的非常透彻的,在自己机器上tune了多卡(发现了很多。这当然都是早就解决了的,测例我们一开始就选择的是AUSURF,后面也是原题,只是精度有点差别,需要更多的显存。我们尝试改了一版Vkfft,后来没cufft快就放弃了,还试图搞了异构,花了挺多时间的,不过这也给他们当并行计算final project了,至少没白花时间。Cardioid我和jyc好好优化了一下,其实就改了一个set和一个MPI_Reduce,就说最后运行的机器只有单机八卡,他之前的做法是要到500nodes才有效果。所以我们就为单node优化了。

Badfs

在ISC结束的时候我拉了一位和我一起写和清华MadFS差不多思路的文件系统,但使用不同实现,不用UCX而用ibverbs,不用rocksdb写放大而用concurrent ART Tree。可是那个同学锅更多,就give up了(所以问题是我校人数太少,PUA太多)。

比赛开始后

开始的时候我们莫名其妙开始跑了,原来是和BU他们名字搞反了,巨硬养老院的Andy是真靠不住。换回来后我们还莫名其妙多了30USD。貌似也退不了。比赛到1个小时的时候莫名我们nfs的home被删了,我们理解为是惊喜。我们重装了了一遍集群才搞定,幸好都是自动化的。Azure上面每台机器只有20G的本地磁盘,/tmp经常写爆,所以只能export TMP=/mnt/shared/tmp。只是注意什么启动阶段什么东西好了。

Q-E很快就用上了"免费机器",我们申请了650core的免费机器跑AUSURF,时间和cost都是全场第一。第二个测例和第三个测例我查了一下网站,算了一下,发现分别nk=4和ntg=2/npool=4最好,加上特调的binder.sh,以及1台8卡A100还有和Ye Luo的唠嗑,我们拿了接近满分。这是第一次拿到两台A100(ND96)的时间。

在第二次高峰的时候我们准备放benchmark,murez咕了去搞mystery app了,有很多坑,现在nfs上面配好。我就负责了HPL和HPCG。第一次拿到的时候发现就拿不到3台以上了,于是通过计算得到全场只有8台8卡A100,我们果断切了另一个集群用脚本抢。可是还是只有三台。总之,不如用于憋死别人吧。至少北大比我们晚一点就没了,导致他们和清华只能用V100.我在这里跑了1次HPCG和10次HPL后就被mystery app的自动调参机接管了,不过mystery app刚开始的时候就有问题,是mpi没配对,准确的说是mpi用了错误的libmpi.so.12,经验不足训练不足吧。这让murez很紧张,这大概浪费了1小时吧,后来我帮他编译成功了。他就任性的用满显存搞事情。全精度,半精度,混合精度的他把batch size调到正好24卡A100从而获得最好性能,不过遗憾是我们没用本地的机器,所以参数都是真的看到结果反哺去调的,清华可以在自己的机器上拿到不错的参数再继续,可是我们社连A100都没有啊,总之就只能这样了(他们用同样的A100机器也能做的比我们好一些,因为参数). IO test是放在tmpfs上跑的,跑了1400,(这里清华可以over madfs。)我们这个阶段也没钱拿HB120rs用于BeeGFS了,所以IO test是不行了。

IO500 最后也没写完,所以最后我们拿了Optane SSD的单盘测试的,拿了个27.2

比赛结束后

发现清华的学生不是状元就是金牌,这些令人仰望的人,我们学校培养的学生,是职业的,有学术训练的工程师和研究者,只能说有阶段性胜利,让我校进出口未来会好一点吧(多来点OI银牌。

总之还有有一点进步空间,只是对我来说没有下一次了,如果这次是最后一次,也许我请的那个人会和我一起写完。不过,真的能提升的也只有日常训练,对代码对系统对AI System的理解。

Yet another Ownership shit in Rust

Yesterday I'm dealing with a Rust pitfalls like below:

pub struct IBStream<'a> {
    qp: Arc<ibverbs::QueuePair<'a>>,
    cq: Arc<ibverbs::CompletionQueue<'a>>,
    mr: ibverbs::MemoryRegion<RdmaPrimitive>,
    pd: Arc<ibverbs::ProtectionDomain<'a>>,
    ctx: Arc<ibverbs::Context>,
}

My initiative is to make the IBStream initial in parallel. As for implementation of ctx is an unsafe code to consume CompletionQueue and cq, mr and pd have different lifetimes, so on initiate the struct, we couldn't make sure ctx's lifetime is long lived than IBStream. We couldn't write the could as below:

pub fn new<'b, A: ToSocketAddrs>(addr: A) -> Result<IBStream<'b>, IBError> {
        let ctx = Self::setup_ctx()?;
        let ctxr: & _ = &ctx;
        let cq = Self::setup_cq(ctxr)?;
        let pd = Self::setup_pd(&ctx.clone())?;
        let qp = Self::setup_qp(&cq.clone(), &pd.clone(), &ctx.clone())?;

        let mr = pd.allocate::<RdmaPrimitive>(2).unwrap();
        Ok(IBStream {
            qp,
            cq,
            mr,
            pd,
            ctx,
        })
    }


The library function specify such lifetime to let the user have to take care of ctx and cq's lifetime, which has some senses. But these thinking of lifetime is too tedious for fast deployment.

How to solve the problem? As Jon put, there's library called ouroboros that the data in the struct has the same lifetime with the outer struct, that they are created and destroyed at the same time.

#[ouroboros::self_referencing]
pub struct ClientSideConnection<'connection> {
    cq: CompletionQueue<'connection>,
    pd: &'connection ProtectionDomain<'connection>,
    #[borrows(cq, pd)]
    #[covariant]
    qp: QueuePair<'this>,
}

When using the struct, if we have to specify the static in one function.

let client = client as *const BadfsServiceClient;
// this is safe because we move client into closure, then execute the closure before function returns
let client:&'static BadfsServiceClient = unsafe{client.as_ref().unwrap()};

Another problem, if I want to specify a lifetime inside a function but the borrow checker think it's not, we could cheat it with the same trick.

All in all, borrow checker is easy to cheat.

QE

GPU 部分

cmake 通过修改开关,只让GPU使用 ptx 及 fortran intrinsic ABI 直接编译,替代 OpenACC的 kernel 实现。MPI 库实现替换为 ucx gpr_copy. AUARF32 时间从 4m59s 提升至 1m51s。 但在多卡上仍就有很大的通讯开销。由于 cuda_ipc 在 x86 架构上只能通过 PCIe 传输,4卡高达1小时左右。即便是开了-nk 2的情况下。 issue

profiling 总结

  1. cuFFT 使用较多, GPU实现的kernel次之,最多的运算是高维矩阵的浮点数运算,但有一定的 cache time locality 的可能,可能的优化方向是 grid 调参, ptx 调优、 Unified GPU memory 利用。
  2. VKFFT

pitfalls

  1. https://github.com/MPAS-Dev/MPAS-Model/issues/554
  2. https://forums.developer.nvidia.com/t/problem-with-nvfortran-and-r/155366
  3. LibGOMP not IMPLEMENTED: fftw/scalapack/hdf5/elpa is not dependent on the compiler's lib.

通过例子更新 wiki Fortran 部分代码

  1. vecAdd 例子 OpenAcc 与 cuda kernel 与 fortran ptx(range) 的比值约为 1.3:1:0.8.
  2. 使用 fortran 调用 cufft 及 cublas

CPU 部分

测试案例 cache 优化

针对 AUARF112 测试案例,在针对 core.F90 中的 scf 场进行 cache 调优

换 malloc 库优化

尝试对比内存使用率

IO500 部分

  1. Rust 编译器踩坑中,深入了解了 Send Sync
  2. 了解 client 中 ctor 的特性。