CUDA中的Unified Memory

  2023年第一天,讨论讨论新的一年AI系统方向会有哪些新的进展。包括硬件、软件,模型优化、系统优化,单设备优化、scale-out优化。

  实验室一师姐,我们去食堂会路过学校内的一个转盘,每天去吃饭的时候她都会贴着转盘走,甚至不惜把裤子弄脏,一天我终于忍住不问她为什么。。。

  她说,师弟,你没学过切线最短吗?

  听她说完后,我觉得非常有道理。自从每天我跟她一样一前一后贴着走后,感觉生活都变了。一天一个小同学从后面说,你看那俩读傻了,你才傻呢,你懂我的世界吗。

  ————————————————————————

  割割割割割割

  介于很多知友问我跟师姐的关系,我还想讲一个事情。

  记得我读研究生一年级的时候,一天晚上和师姐做完实验回寝室,在路上师姐突然驻足在一电线杆前,我刚要问怎么了,师姐怒砸了一下电线杆(注意是用手),我吓懵了。。。

  经过打听才知道,有一个男生追求她,然后她给她妈妈竟然打电话说想谈恋爱了,师姐的妈妈义正言辞的说,你才博二啊,要以学业为重,现在根本不是谈恋爱的时候,耽误了学业怎么办。

  我觉得师姐的妈妈说的非常有道理,不能早恋,还没毕业,恋爱的事情是我能考虑的吗。

  ————————————————————————

  割割割割割

  知友踊跃的态度,让我受宠若精,深受感动。所以再次更新师姐的一件事情

  当然这次师姐是受害者,而且这次确实傻了,但不是读傻。

  我们博士是两人间,一般床是并排的,师姐为了跟室友说话省劲,把床头搬成对着的那种,两人头对着头睡觉。师姐的室友学无机材料的,估计搬砖太累了,不幸得了哮喘。

  听师姐描述,一晚她睡得正香,梦到做了三年的实验终于成功了,正在她开心大笑旋转跳跃的时候,她听到了一阵阵急促的喘息声,而且越来越急促,越来越大。她睁开了兴奋的眼睛 的时候,看到了一幅画面,让她差点离开这个世界。 师姐的室友当时类似于这个样子,当然当时没开灯是黑的,只有月光如水般阴柔的撒在室友的脸上

  

  长发飘飘的她坐起来低着头看着师姐,大口喘息着对着师姐喊,药。。。药,给我拿药!师姐说,室友的吐沫星子喷到了她鼻尖上救了她,让她清醒了一些。

  我是理科生,语言难以形容师姐当时的状态。玩

  割割割割割割割

  五年了,整整五年了,一直有人问我和师姐怎么样了。是这样的。。。。。。。。师姐三年前跟一个开大G的跑了,从那以后我的心也就只剩下科研了。那天我看着大G的屁股。。。。。。。。。。。。。。。。。。真想上去踹一脚,但是我忍住了,告诉自己不能冲动,只要sci发出来,我就打印出来,然后一页一液甩她身上,让她知道什么才是真正有能力的男人!!!

  割割割割割割割割割割割割割割割割割割割

  三年来我发了3篇论文,都是高档次4区论文!最高区了,但是我已经淡然了,成功男人可能都是相似的吧,我突然理解了马云,刘强东,王健林,只是领域不同罢了。我清醒了,好久没看到大G和师姐了,估计师姐早就和他分了,暮然回首还是有才华的好吧。我也原谅她了,只要她认错,还是可以回到我的身边的,我点开了那个屏蔽已久的朋友圈。。。。。。。。。。。。。。。。

  这她孩子怎么都有了!还都会写作文了!

  我抖了抖我穿的大牌The south face,感觉我没了face.

  感觉杰青那年比长江更兴奋一些,收入没改变,生活没改变,继续996,继续搞科研。

  遇到一个成绩出类拔萃的北京人。

  他在南大念天文。

  你觉得他为什么不去清北。

  他一直为紫台的研究生在南大上课,却只能拿科大的毕业证惋惜。

  顶尖的学科和所谓的学校排名无关了。

  相比之下,复旦就平均多了。复旦是分数在top3,因为复旦在上海啊,复旦的学生确实更好找工作啊。

  但是南大的物理化学数学天文之类的理科是真在top3里的。

  不太清楚末流211是有多末流,

  北邮这种顶尖211的cs难度一般情况是跟末流985的cs难度差不多,当然各个学校的强组不再此范围内。但北邮主要是有学科和地域加持,所以北邮不好说,但末流985概率还是有的。

  而且你rank刚卡入营线,无法保证夏令营,不过九推可以试一试。

  其他内容可参考我的经验贴

  2023CS保研经验分享(清深、上交、南大LAMDA、同济、东南Palm等)

  保研名额下发流程是这样的。

  每年教育部会根据各个学校当届学生人数以及还学校往年的学生毕业去向质量 科研水平 学校综合能力等等这种给学校分配名额。

  学校拿到名额后根据各级学院的各类指标来进行名额分配。

  学院拿到名额后,一般都是按专业分配,因为不同专业的课程是不一样,如果不按专业分,这样有失公平。并且一般为了保证一定的公平性, 各个专业的分配名额占总人数的比例是都差不多的。可能会根据专业title和学生水平有一定倾斜,但不会很大。

  在CUDA 6中,NVIDIA引入了CUDA历史上一个最重要的一个编程模型改进之一,unified memory(以下简称UM)。在今天典型的PC上,CPU与GPU的内存是物理上独立的,通过PCI-E总线进行连接通信。实际上,在CUDA 6.0之前,程序员必须在编程期间很清楚这一点,并且反应在代码中。必须在CPU和GPU两端都进行内存分配,并不断地进行手动copy,来保证两端的内存一致。

  Unified memory在程序员的视角中,维护了一个统一的内存池,在CPU与GPU中共享。使用了单一指针进行托管内存,由系统来自动地进行内存迁移。

  OK, talk is cheap, show me the code.

  首先以排序文件中的数据来举例,简单对比一下CPU代码(左)与带有UM的CUDA代码(右):

  可以清晰地看到,两段代码惊人地相似。

  仅有的不同在于:

  GPU版本使用cudaMallocManaged来分配内存,而非malloc由于CPU与GPU间是异步执行,因此在launch kernel后需要调用cudaDeviceSynchronize进行同步。在CUDA 6.0之前,要实现以上的功能,可能需要以下的代码:

  到目前为止,可以看出主要有以下的优势:

  简化了代码编写和内存模型可以在CPU端和GPU端共用一个指针,不用单独各自分配空间。方便管理,减少了代码量。语言结合更紧密,减少与兼容语言的语法差异。更方便的代码迁移。等等。。。从之前的描述来看,好像也并没有减少很多代码量。。那我们接下来考虑一个十分常见的情况,。当我们拥有一个这样的结构体:

  我们可能要进行这样的处理:

  但在CUDA 6.0后,由于UM的引用,可以这样:

  很明显,deep copy的情况下,UM极大地减少了代码量。在UM出现之前,由于两端地址空间不同步,需要进行多次的手动分配和拷贝内存。尤其对于非cuda程序员,十分不习惯,而且十分繁琐。当实际数据结构更加复杂时,两者差距会更加显著。

  而对于常见数据结构--链表,本质上是有指针组成的嵌套的数据结构,在没有UM的情况下, CPU与GPU间共享链表非常难以处理,内存空间的传递很复杂。

  这时使用UM,可以有以下的优势:

  在CPU和GPU间直接传递链表元素。在CPU或GPU任一一端来修改链表元素。避免了复杂的同步问题。不过实际上在UM出现前,可以Zero-copy memory(pinned host memory)来解决这个复杂的问题。但即使这样,UM的存在仍有意义,因为pinned host memory的数据获取受制于PCI-express的性能,使用UM可以获得更好的性能。对于这一问题,本文暂时不进行深入讨论。

  由于现代C++中尽量避免显式调用malloc等内存分配函数,而使用new来进行wrap。因此可以通过override new函数来使用UM。

  通过继承该class,从而让custom C++ class实现UM的pass-by-reference。而通过在constructor中,调用cudaMallocManaged来实现UM下的pass-by-value。下面以一个string class来说明:

  实际上在CUDA 4.0就开始支持Unified Virtual Addressing了,请不要与Unified Memory混淆。尽管UM是依赖于UVA的,但实际上他们并不是一回事。要讲清楚这一个问题,首先我们要知道UVA所关心的内存类型

  device memory (可能在不同的gpu上)on-chip shared memoryhost memory 而对于SM中的local memory,register等线程相关的内存,很明显不在UVA所关注的范围。因此UVA实际上是为这些内存提供统一的地址空间,为此UVA启用了zero-copy技术,在CPU端分配内存,将CUDA VA映射上去,通过PCI-E进行每个操作。而且注意,UVA永远不会为你进行内存迁移。

  关于两者之间更深入的对比,和性能分析,超出了本文讨论范围,也许会在后续的文章中继续讨论。

  问:UM会消除System Memory和GPU Memory之间的拷贝么?答:不会,只是这部分copy工作交给CUDA在runtime期间执行,只是对程序员透明而已。memory copy的overhead依然存在,还有race conditions的问题依然需要考虑,从而确保GPU与CPU端的数据一致。简单的说,如果你手动管理内存能力优秀,UM不可能为你带来更好的性能,只是减少你的工作量。问:既然并没有消除数据间的拷贝,看起来这只是compiler time的事情,为什么仍需要算力3.0以上?难道是为了骗大家买卡么?wait....到目前为止,实际上我们省略了很多实现细节。因为原则上不可能消除拷贝,无法在compile期间获知所有消息。而且重要的一点,在Pascal以后的GPU架构中,提供了49-bit的虚拟内存寻址,和按需页迁移的功能。49位寻址长度足够GPU来cover整个sytem memory和所有的GPUmemory。而页迁移引擎通过内存将任意的可寻址范围内的内存迁移到GPU内存中,来使得GPU线程可以访问non-resident memory。简言之,新架构的卡物理上允许GPU访问”超额“的内存,不用通过修改程序代码,就使得GPU可以处理out-of-core运算(也就是待处理数据超过本地物理内存的运算)。而且在Pascal和Volta上甚至支持系统范围的原子内存操作,可以跨越多个GPU,在multi-GPU下,可以极大地简化代码复杂度。同时,对于数据分散的程序,按需页迁移功能可以通过page fault更小粒度地加载内存,而非加载整个内存,节约更多数据迁移的成本。(其实CPU很早就有类似的事情,原理很相似。)