-
Notifications
You must be signed in to change notification settings - Fork 0
分布式高性能深度学习12月29日
CPU和GPU体系结构差异
在经典的CPU体系结构里面,有一个比较大的内存单元,然后由cache,CPU体系结构中由比较多的寄存器,但是和GPU相比较,寄存器还是比较有限的,CPU体系为了进行更多的逻辑分支,预测包括流水线一些排布,可以对一条流水线中不同的指令有一些预测和乱序执行,读和写计算,指令如果不是相互依赖的,如果不是必须按序执行的话,CPU是有足够的能力进行指令之间的重新排布,能组织多个写,保证一个大的读写片和计算是可以同步来执行的,因为增加了各种各样逻辑判断的、预测的分支,所以导致CPU体系下计算的单元数是有限的,GPU相对CPU来说,预测和调度会弱很多,以计算为主的设计结构,更适合大规模数据并行,在新的GPU体系之下,针对for、while这种循环结构,包括针对硬件单元的设计,对tensor core支持非常好,寒武纪对经常用到的计算,常用的计算单元,通过硬件化的方式,使得整个计算变得更快,用硬件的实现代替软件的实现,针对特定的层,算子,进行硬件化的过程,高层的指令,函数调用的方法,粒度比较大的都迁移到硬件组织的这种方式。
CUDA生态
对编程语言的支持比较完善,不同代GPU之间,计算核的数量会增加很多,增加SM的数量,增加计算单元,对精度的支持也是不同的,上层从一些应用层软件来说,一些库也会越来越完善
GPU计算扩展性
不同代GPU最简单的方式,可以用SM方式,由多处理器方式来进行扩展,每个SM里面支持的,每个SM中可以加载的block个数可以做到一个扩展,从每台服务器的角度来说,可以有多个节点的方式来增加它的扩展性,再到多...方式,有些特殊的连接方式来提高它的整个的通信带宽,也就做到了这种持续的扩展,然后深入到每个GPU内部的调度过程,任何一个kernel函数,我们要执行的一个核心计算,比如我们实现了一个矩阵乘,或者一个线性变换,向量的表示,映射到内核的计算,会以grid方式来组织,grid是由n个block来构成,不同的GPU可以支持的block个数可以通过参数来获取,每个block里面有相应的不同的线程组,CPU里面也有thread概念,GPU里面也有thread概念,GPU里面thread概念是一个硬件级线程,CPU里面thread粒度是非常大的,调度的过程中需要一些寄存器,压栈的方式,很可能就是把很多的数据保存在硬盘上,很可能交换硬盘上数据格式,但是GPU上thread切换是很快的,可以直接压到寄存器组里,因为它的寄存器的数目是远远多于CPU的,所以通常需要上下文切换的时候,一组计算完,另一组调度的时候,会有更快的切换性能,GPU里面有万兆的线程调度器,这种线程调度能力会越来越强,因为寄存器扩展了之后,它的计算性能也会有一个比较高的提升
在做CUDA开发时,需要预估一下线程占用寄存器的数量,导致block的使用量,如果是参数导致寄存器不够用,比如程序在CUDA内核里面声明了很多局部变量,但是在寄存器占用完的情况下,会被挤到local memory,甚至直接向下,挤到写从,写从的读写性能是多少M之类的,与寄存器的读写速度相差几百倍,上千倍,所以说对程序的规划,写的过程中,需要关注block的数量,然后是寄存器的用量,如果单线程占用寄存器数量比较多的话,会导致整体可以启动的block数会有一个比较大的变化,因为单线程占用较多,导致block减少的话,会对整个性能还是会有较大的影响的,