
GPU计算建立在并行计算、并行图形系统和流处理等领域的早期研究成果之上。这些技术是政府资助的学术研究历经30余年发展而成的,正是这一系列积累,奠定了现代GPU计算的基础,也间接推动了人工智能等领域的革命性突破。
学习计算机时,通常会了解到中央处理器(CPU)逐条执行指令序列。但实际上,芯片包含数十亿个并行开关的晶体管,并通过导线连接——开关和导线是物理计算机的基本组成单元,它们可以同时运行。此外,晶体管开关消耗的能量极少,而导线通信则消耗的能量要多得多:通信需要功率才能将信号从一点发送到另一点,功率随距离增加,若为芯片之间的信号传输,功率消耗更是巨大。
虽然顺序计算机比并行计算机更容易理解,但顺序计算机必须由并行开关的晶体管和同时传输信息的导线来实现。它会使用大量晶体管并行计算结果,再以符合顺序执行的方式精心组装这些结果。这种为营造顺序执行假象而采取的方法,在功耗和性能方面都存在缺陷,且随着可用晶体管数量的增加,这种缺陷会更加明显。在现代半导体技术中,构建计算机的自然方式是设计并行计算机,而GPU比CPU效率更高,核心原因就在于它是大规模并行计算机。
GPU计算建立在早期并行计算工作的基础上。与所有并行计算机一样,运行在GPU上的并行任务或线程必须彼此同步和通信:通信对于一个线程使用另一个线程产生的数据至关重要,同步则用于在数据可用时发出信号,以确保使用正确的值。并行计算、同步和通信的许多基本原理,都源于政府资助的学术研究。
由加州理工学院Chuck Seitz领导、DARPA资助的Cosmic Cube项目,开发了并行计算的许多基本原理,其硬件成为Intel iPSC、Delta和Paragon机器以及一些早期美国能源部ASCI机器的基础模型。Cosmic-C编程语言引入的异步消息传递和集合运算,后来以消息传递接口(MPI)的形式,成为大型并行机器编程的标准。
同样由DARPA资助,麻省理工学院(MIT)的J-Machine和M-Machine项目,开发了低开销的通信和同步机制,以及现代互连网络的许多关键方面。这些机制使得并行性能够以非常精细的粒度被利用,一个可调度的工作单元甚至可以只有10或20条指令,而J-Machine的许多特性也被Cray T3D和T3E计算机直接采用。
虽然并行图形和图像处理计算机不如传统的并行计算和超级计算机广为人知,但它们的发展历史同样悠久。图像的处理和生成需要大量计算:例如,一台每秒执行一百万条指令(1MIPS)的计算机,对一张一百万像素图像的每个像素执行一次算术运算,处理一张图像就需要一秒钟。而电影和游戏中3D虚拟世界的渲染,每个像素的计算量比普通图像处理高出几个数量级——现代电影生成的图像,每个像素大约需要进行十亿次浮点运算。因此,为了在实践中发挥作用,图形和图像处理必须依赖能够并行处理大量数据的高性能并行超级计算机。
早期由DARPA资助的研究项目中,斯坦福大学吉姆·克拉克(Jim Clark)领导的几何引擎(Geometry Engine)极具影响力,它直接促成了硅谷图形公司(Silicon Graphics)的成立,该公司是3D图形工作站开发的先驱,其硬件架构和OpenGL软件库,定义了现代GPU的架构雏形。
另一个值得关注的政府资助研究项目,是北卡罗来纳大学亨利·福克斯(Henry Fuchs)及其合作者领导的像素平面(Pixel Planes)系列高性能图形系统。其中,Pixel Planes 5实际上是一台相当通用的单指令多数据(SIMD)计算机,能够在128×128的图像上运行并行计算。除此之外,早期并行图形和图像计算机的例子还包括美国宇航局的大规模并行处理器(MPP)、Ikonas图形系统和皮克斯图像计算机。
早期的GPU采用与早期SGI工作站类似的固定功能图形管线,直到Nvidia公司将整个OpenGL图形管线集成到单个芯片上,才正式引入“GPU”这一术语——1999年推出的Nvidia GeForce 256拥有1700万个晶体管,是首款商用GPU。
早前在皮克斯工作期间,汉拉汉开发了RenderMan系统,用于生成照片级真实感图像,这一系统彻底革新了电影行业,因为它能够生成可与摄像机拍摄的实景无缝融合的画面。RenderMan的关键组件是着色语言,它使用户能够扩展系统,从而模拟复杂的材质和光照效果。
尽管早期GPU采用固定功能流水线,但它们由可编程组件构成,只是这些处理单元会随系统和代际变化而变化,因此亟需一种可移植的编程模型。由于GPU的主要应用领域是电脑游戏,将RenderMan着色语言适配到GPU上成为顺理成章的选择,这样游戏开发者就能创建新的光照和阴影效果。
在斯坦福大学,一项由DARPA资助的项目,为当时的GPU设计并实现了一种实时着色语言(RTSL),这种着色语言程序现在被称为着色器。博士后研究员比尔·马克(Bill Mark)领导了斯坦福RTSL的设计,之后他加入英伟达公司,与另一位斯坦福大学前研究生库尔特·阿克利(Kurt Akeley)一起改进这项技术,创建了Cg着色语言——Cg为微软的HLSL和OpenGL的GLSL的开发奠定了基础。
人们很快意识到,这些早期的着色语言足够灵活,能够实现科学计算中的许多算法。研究人员将矩阵乘法、线性求解器、流体流动求解器和分子动力学等算法,适配到着色器上运行,这也促成了通用图形处理器(GPGPU)计算的发展。
斯坦福大学在DARPA和DOE(美国能源部)的资助下,开发了Imagine流处理器和Merrimac流式超级计算机,由此发展出流处理技术。流处理是一种并行计算形式,能够显著提高算术强度(计算量与带宽的比值)。如前所述,处理器消耗的大部分功率都用于通信,芯片间信号传输尤其耗电,且片外通信的速度远低于片内通信。
流处理可有效降低对内存带宽的需求:一是利用生产者-消费者局部性,让生产者阶段能够将其结果转发给消费者阶段,无需进行内存读写操作;二是将计算组织成称为内核的函数,每个内核接收一个数据包,对其执行特定函数后输出另一个数据包,且函数中的算术运算次数大于内存读写次数。这两种技术显著减少了内存访问次数,大幅提升了流处理架构的效率。
在流处理器中,计算被组织成多个内核,每个内核负责生成和使用数据流:生成内核将输出流写入流寄存器文件(SRF),使用内核则从SRF读取输入,无需将数据写入或读取内存。通过适当调度,使数据流的批处理大小与SRF的容量相匹配,这种组织方式能让应用程序维持极高的算术强度(算术带宽与内存带宽之比)。
由DARPA资助的Imagine流处理器设计和构建项目,于1997年在麻省理工学院启动,同年晚些时候转移到斯坦福大学。Imagine是一款图形和媒体处理器,旨在处理信号和图像工作负载,它由多个带有本地寄存器文件的并行运算单元、一个中央流寄存器文件和一个内存系统组成。内核从流寄存器文件中读取数据流,将中间结果通过本地寄存器文件传递,并将输出流写回流寄存器文件,供下一个内核读取。
Stream-C编程语言是为Imagine系统开发的,它扩展了C编程语言,增加了描述内核和流的结构。为了优化和评估该架构,研究人员开发了大量图形、信号处理和图像处理应用程序,其在纹理映射光栅图形方面的性能,与当时的固定功能GPU相当。
在一次DARPA首席研究员会议上,本文作者意识到这项技术可应用于高性能计算,进而构思了Merrimac项目。斯坦福大学能源部高级计算信息中心(DOE ASCI Center)的计算机科学(CS)部门因此调整方向,致力于推进这一高性能计算方法,该中心的年度报告详细记录了流处理技术的发展历程。
Merrimac架构旨在将流处理应用于科学领域,与Imagine架构相比,其主要改进包括:增加科学计算所需的数据类型(例如FP64);将架构扩展到通过互连网络连接的多个节点,以应对大规模问题;增加一系列弹性功能,以在合理的故障率下支持大规模计算。
Stream-C编程语言随后演变成了Brook,其核心思想是将流式编程的理念与更传统的并行数据计算相结合,内核函数成为维持高运算强度的关键处理原语。Brook算法最初是为21世纪初的GPU设计的,这些GPU运行可编程的顶点着色器和片段着色器——着色器实现了内核,但指令数量和寄存器数量有限。
诸如map、reduce/scan、filter、gather和scatter等常用的数据并行编程原语,是通过在底层图形着色器之上构建虚拟数据并行计算机来实现的。这种抽象使得大量现有的并行算法能够在GPU上运行,并逐步消除了早期着色器的局限性。
内核早期应用于执行高强度运算的典型例子是稠密矩阵乘法,它是现代神经网络算法的基础。执行矩阵乘法时,需要读取两个n×n矩阵,写入一个n×n矩阵,整个过程需要n³次乘法运算并进行累加,因此算术复杂度为O(n³)。这一特性催生了针对带缓存CPU的高效分块矩阵乘法方法,而这种分块方法在GPU上运行时效果同样良好。
斯坦福大学ASCI中心的数值科学家们,将多个科学代码移植到Brook平台,以便在Merrimac模拟器上运行,这些代码包括计算流体动力学、磁流体动力学和n体模拟。其中,n体模拟是高效GPU应用的典型例子:在天体物理模拟中,原子对之间的作用力由万有引力定律给出,而非束缚原子之间的相互作用则用Lennard-Jones势(甚至更复杂的经验势)来近似,这些函数需要大量算术运算;在这类模拟中,相邻原子会存储在“邻居列表”中,因此分子动力学模拟很快成为GPU的主要应用之一。
GPU和流处理器的一个关键特性,是它们具有多种形式的硬件并行性。每个GPU由多个核心组成,每个核心包含一个SIMD处理单元(通常为32线程),且每个核心都是多线程的。回想一下,GPU最初是为游戏应用开发的,这些应用的性能取决于将纹理应用到三角形的效率——纹理映射涉及计算三角形内每个像素片段的纹理坐标,再使用这些坐标从图像中获取纹理,这些纹理获取具有空间局部性,但时间局部性很差。
空间局部性可以通过小型缓存处理,但由于缺乏一致性,缓存无法处理时间局部性。高效的纹理映射要求GPU隐藏这些纹理获取的延迟,早期GPU通过这样的方式实现:当一个片段请求纹理时,暂停该片段的执行,立即切换到处理另一个片段。这是一种简化的多线程版本,意味着GPU需要同时运行多个并行线程,任务总数等于核心数乘以SIMD运算单元(称为线程束)数再乘以线程数。例如,Blackwell B200 GPU拥有384个流式多处理器(SM),每个SM包含64个常驻线程束,每个线程束包含32个线程,因此该GPU上可以同时执行786432个任务。
流处理架构和编程系统,通过人员调动从斯坦福大学转移到了英伟达。英伟达的架构师约翰·尼科尔斯(John Nickolls)听说了流处理技术后,于2003年聘请比尔·戴利(Bill Dally)担任英伟达NV50架构的顾问(NV50于2006年以G80的名称发布),流处理器的许多特性都被融入到该架构中,其中NV50的“共享内存”功能,就起到了Imagine和Merrimac中SRF(流寄存器文件)的作用。
伊恩·巴克(Ian Buck,Merrimac项目的研究生,也是Brook的主要开发者)于2004年加入英伟达,他与约翰·尼科尔斯(John Nickolls)合作,将Brook发展成为CUDA。CUDA融合了Brook和Cg(图形着色语言)的最佳特性,并采纳了Brook程序员的反馈意见。而迈克·休斯顿(Mike Houston,该项目的另一位研究生)加入了AMD,并直接使用Brook作为其GPU的编程语言。2006年,G80(NV50)和CUDA在超级计算大会上正式发布。
2006年CUDA发布时,了解并行编程的人寥寥无几,更不用说GPU流编程。为了弥补这一人才缺口,David Kirk等开设了面向大学教授的CUDA编程课程,大力推广GPU计算。参加过这些课程的教师,后来又向成千上万的学生教授了CUDA并行编程。从Cosmic Cube、J-Machine和M-Machine等平台借鉴的并行计算技术,不仅应用于单个GPU内部(用于协调多个流式处理器),还用于构建多节点GPU系统,以解决大型计算问题。
现代机器学习依赖于三个关键要素:海量数据集、具有多层和权重的大型模型,以及用于优化权重的计算能力。核心算法(深度神经网络、卷积神经网络、反向传播训练和随机梯度下降)早在20世纪80年代或更早时期就已出现;大型标注数据集,例如PASCAL和ImageNet,出现于21世纪初;近年来,诸如将文本嵌入向量空间等技术进步,使得深度学习能够应用于自然语言处理,而Transformer(仅依赖注意力机制)则用易于训练且具有历史信息的神经网络,取代了难以训练的带隐藏状态的循环神经网络。
GPU计算的出现,使得使用海量数据集训练大型网络成为可能,且成本更低。一旦这项能力得到验证(例如AlexNet和GPT),人工智能的能力便迅速提升,而人工智能的快速普及,又进一步推动了GPU计算系统的持续改进。
现代机器学习赖以实现的GPU计算技术,主要得益于政府资助的30年学术研究。并行计算、并行图形系统和流处理领域的研究,共同为GPU计算奠定了坚实基础;许多参与这些研究项目的学生毕业后进入业界,推动了技术转移和创新产品开发。
其中,斯坦福流处理项目向GPU计算的转化尤为直接——学术界的Brook语言演变成了CUDA,流处理器功能也被集成到G80 GPU中。GPU及其计算着色器提供的高效、易于编程且性能极高的计算平台,推动了当前机器学习领域的革命性发展,恰好弥补了算法和数据长期存在所缺失的关键要素,成为连接学术研究与产业革新的重要桥梁。
本文转自媒体报道或网络平台,系作者个人立场或观点。我方转载仅为分享,不代表我方赞成或认同。若来源标注错误或侵犯了您的合法权益,请及时联系客服,我们作为中立的平台服务者将及时更正、删除或依法处理。
