遗憾的是,从美国当前的高端芯片出口政策看,以英伟达H200为代表的美国高端AI芯片短时间内暂时无缘国内。但国内AI技术还是得不断迭代发展,国产替代行不行得通?
那么问题来了,高性能GPU 被限制,普通GPU不能用吗?CPU和GPU差在哪里?
在解答这些问题之前,我们先来了解下目前哪些场景使用了GPU,以及为什么说大多数程序员都应该了解GPU。
说起GPU的应用起源,就不得不说打游戏。可以说在GPU发展的前期,游戏发展占半边天。PS5和Xbox游戏机都内置了GPU芯片。
如果你是一位游戏爱好者,你大概率会知道购买游戏设备,会更看重其GPU性能。即所谓的“CPU决定下限,GPU决定上限”。
GPU大体决定了游戏分辨率、特效能开多高,对于用户的游戏体验起到关键性作用。
其次就是前几年还比较流行的加密货币、“挖矿”。比特币等加密货币的火爆带动矿卡GPU需求,Nvidia的股票也是成倍的翻。矿机算力的大小决定挖矿的速度,算力越大,挖矿越快。
其次是自动驾驶场景,自动驾驶场景一般在处理分析实时数据后,需要在毫秒的时间精度下对行车路径、车速进行规划,保障行车过程安全,对处理器的计算速度要求也较高。
而GPU采用流式并行计算模式,可对每个数据行独立的并行计算,擅长大规模并发计算,正是自动驾驶所需要的。
再其次就是深度学习,随着Transformer的出世,AI大模型其参数量从亿级飙升到万亿级,训练时间从小时到天级,使得大模型对算力提升提出要求,而这时高性能GPU集群正好可以满足这个要求。
当然,除此以外手机、平板等移动设备,音响,手环,监控等都已被嵌入并应用了GPU。
未来GPU将不仅仅停留在这些领域,云计算和大数据分析、机器人技术、虚拟现实和医疗目前也有很多开源的Demo已经在探索并应用。
过去的十多年,GPU依靠着上述的热点领域不断地拓展英伟达史上最强AI芯片都发布了你还不知道GPU的原理和前景,而大多数的程序员依然是在CPU和顺序编程中成长。
未来的十多年,每一个程序员都需要像了解CPU一样了解GPU工作原理,以及并发编程的工作方式。
GPU犹如一群小学生,CPU是一个大学教授,相比能力来说CPU完胜GPU,但对于大量浮点计算来说,还是GPU算的快。
我们可以说CPU是全能选手,GPU是专精选手。GPU一般无法独立工作,其工作都是由CPU触发的。
CPU 被设计为顺序执行指令,为了提高顺序执行性能,多年来 CPU 设计中引入了许多功能,包括指令流水线、乱序执行、推测执行和多级缓存等。
这一设计方向受到了它们在视频游戏、图形、数值计算和现在深度学习中的使用的影响。
所有这些应用程序都需要以非常快的速度执行大量线性代数和数值计算,因此人们对提高这些设备的吞吐量投入了大量注意力。
由于CPU指令延迟较低,CPU 可以比 GPU 更快地执行两个数字相加。
然而,当进行数百万或数十亿次此类计算时,GPU 由于其巨大的并行性而比 CPU 更快地完成这些计算。
英特尔 24 核处理器的 32 位精度吞吐量为 0.66 TFLOPS。而且,GPU 和 CPU 之间的吞吐量性能差距逐年扩大。
CPU 将大量芯片面积专门用于可减少指令延迟的功能,例如大缓存、更少的 ALU 和更多的控制单元。
相比之下,GPU 使用大量 ALU 来最大化其计算能力和吞吐量,它们使用非常少量的芯片区域作为缓存和控制单元,使得其具有很高的延迟。
要真正的用好GPU,或者使用GPU进行性能加速,你就必须切实的了解GPU的架构,尤其是不断升级迭代的GPU产品,需要做好软硬一体的开发。
这不像很多基于CPU的软件工程师一样,即使我不了解不同CPU产品的特点,也能完美高效的完成运行。
但GPU硬件真的那么复杂吗?其实也没有,建议未来所有工程师都应该深入的了解GPU的架构原理,这样才能更好的适配和应用。
SM是什么呢?说人话就对GPU核心进行分组管理,其中一组GPU core(线程组)就是SM。
当然了每一个分组的SM,也会分配一定的存储器,如上图所示的Memory。
通常称为共享存储器或暂存器,在所有内核之间共享。同样,SM 上的控制单元资源由所有核共享。
除此之外,每个 SM 还具有多个功能单元或其他加速计算单元,例如张量核心或光线追踪单元,以满足 GPU 所满足的工作负载的特定计算需求。
GPU 有多层不同类型的存储器,从访问速度来看,这些存储结构按照从高到低排序依次是:
RMEM(寄存器)>
SMEM(共享存储)>
CMEM(常量存储)>
TMEM(类常量存储)>
LMEM(本地存储)>
GMEM(全局存储)
上面中虚线中表示的就是一个SM中的存储结构,每一个SM都包括寄存器、共享内存、常量内存和L1 cache。
值得注意的是,我们平时所说的Nvidia H100 拥有 80 GB 显存,指的就是Global Memory全局存储,它是一种高容量、高带宽的DRAM。
由于距离SM较远,全局内存的延迟相当高。然而,片上存储器的几个附加层和大量计算单元有助于隐藏这种延迟。
一般一台服务器中一般不超过 16 张卡,最为常见的就是单机8 卡 GPU 服务器。
如上图所示,其中 CPU0 和 CPU1 通过 QPI 互联,QPI(QuickPath Interconnect)是一种用于高性能处理器间通信的接口技术,提供了一个高速、点对点的数据通路,可以实现低延迟和高带宽的处理器之间的通信。
如图所示,GPU 0 和 GPU 4 之间没有直接通路,需要借助其他途径间接通信。
多台机器一般通过交换机相连,多机间的CPU与CPU通信一般需要经过Network Switch通信,通常基于socket原理进行通信,需要经过用户态与内核态的多次数据拷贝。
可以将数据直接从一台计算机的内存传输到另一台计算机,无需双方操作系统以及 CPU 的介入,IB 单网口速度支持从 10Gb/s(SDR) 到 56Gbps(FDR)。
如果想在以太网环境支持 RDMA 的标准,可以采用RoCE(RDMA over Converged Ethernet)通信技术,其无需复杂和低效的 TCP 传输,可以实现多机通信间的“零拷贝”,大幅降低通信延迟。
CUDA是Nvidia花了十年时间打造的一套编程生态,经历了投资人各种不理解,现在已经成为Nv最强护城河。
在 CUDA 中,以类似于 C 函数的形式表达要在 GPU 上运行的计算,该函数称为内核。
在这个例子中我们以一个内核将两个数组向量作为输入,将它们按元素相加并将结果写入另一个向量数组中。
原本在CPU上的实现,我们可能需要实现一个for循环,依次遍历数组,并将数据相加写出到结果数组中。
在GPU上,最简单的实现就是为数组中的每个加法运算分配一个线程,分配的总线程数为数组的长度,这样同时进行计算,一次即可计算完成。
这就需要GPU可以实现调度管理和合理的分配线程,在Nvidia GPU上为管理所有的线程,线程首先被分为多个Grid(网格),每一个Grid中又被分割为多个Block(线程块),每一个Block块由一个或多个线程组成。
在申请线程数,按照网格和线程块进行申请,如果没有足够的可用线程,就得希望每个线程处理多个数据。
在实现上,GPU编程包括两部分,CPU上执行的主机代码(Host), GPU上执行的设备代码(GPU)。
如上图,展示的是CPU上执行的代码,它包括读取CPU上数组数据,申请GPU上的数组空间,将CPU数组拷贝到GPU以及使用配置的线程网格启动GPU内核。
如果这个线程id小于数组的长度n,就执行该线程所对应位置的加法,这样讲O(n)的计算转换为了O(1)。
将数据从主机复制到GPU设备;(当然在最新的 GPU 设备中,我们还可以使用统一虚拟内存直接从主机内存中读取数据)
SM 通过获取并向Warp所有线程发出相同的指令来一起执行(单指令多线程);
然而这次会将进一步在算力上做性能,这显然已不符合国内大模型长远训练的需求。
英伟达首席科学家Bill Dally曾表示:「随着训练需求每6到12个月翻一番,这一差距将随着时间的推移而迅速扩大。」
百度内部已经下令其AI系统“文心一言”使用的芯片,改向华为采购昇腾(Ascend)910B系列AI芯片。
通过深入理解Nvidia GPU的原理和CUDA生态,我们可以借鉴其优秀之处,实现它山之石可以攻玉,从而提升我们对GPU硬件架构的理解。