Stephen Jones, GTC 2023
报告开篇引用了NVIDIA CEO Jensen Huang的论断:“摩尔定律已死(Moore's Law is dead)”。
这一论断进一步阐释为:计算不再仅仅是芯片问题,而是一个软件和芯片协同的问题。这为后续探讨超越传统芯片缩放的计算新范式奠定了基础。
摩尔定律的第一个发展阶段由登纳德缩放定律主导,该阶段持续至约2007年。其核心思想是通过不断缩小晶体管的线宽(line size)来实现性能的翻倍。
大约在2005-2010年间,登纳德缩放达到了物理极限。随着线宽缩小,功耗密度增加导致散热问题难以解决,使得单纯提高处理器频率的路径不再可行。如下图所示,处理器频率在2005年后趋于平缓,增长停滞。
为了继续提升性能,行业转向了增加处理器核心数量的策略。下图右侧展示了从2005年左右开始,处理器核心数量呈指数级增长的趋势。
资料来源:Karl Rupp, "40 years of microprocessor trend data", https://github.com/karlrupp/microprocessor-trend-data
随着登纳德缩放的结束,摩尔定律进入了第二阶段,即单晶片缩放。这一阶段从约2007年持续至今,其主要特征是通过在单个芯片上集成越来越多的核心来提升计算能力。
单晶片缩放同样面临物理极限。在半导体制造的光刻工艺中,通过光罩(reticle mask)将电路图案投影到晶圆上。光罩的尺寸存在上限,这限制了单个芯片所能达到的最大面积,即“光罩极限”。这使得通过无限增大单晶片面积来增加核心数量的方法变得不可行。
随着单晶片缩放逼近极限,摩尔定律进入了第三个阶段:多晶片缩放。该阶段始于当前并延伸至未来,其核心思想是通过组合多个独立的晶片(die)来继续提升计算能力,从而绕过单晶片的尺寸限制。
多晶片缩放可以通过2D(将多个晶片并排封装在同一基板上)或3D(将多个晶片垂直堆叠)的方式实现,从而构建出远超单个光罩极限的强大处理器。
为了克服光罩极限,硬件设计转向了专业化和异构化。异构(heterogeneous)指由性质截然不同的部分组成。在硬件领域,这意味着集成多种专用的处理单元,每种单元负责处理特定类型的计算任务,以提高整体效率。
例如,现代GPU中集成了浮点运算单元、纹理映射单元、光栅化单元和向量单元等多种专用硬件。
以NVIDIA Ada微架构为例,它在一个图形处理集群(graphics processing cluster)中集成了多个纹理处理集群(TPC),每个TPC又包含流式多处理器(SM)。每个SM内部则包含了用于不同任务的专用核心,如用于图形的第三代RT Core、用于AI计算的第四代Tensor Core,以及传统的FP32/INT32计算单元等。这种设计体现了高度的硬件异构化。
软件同样由不同语言编写的异构组件构成。应用程序通常会结合使用多种组件和库。
以Python中的科学计算为例,用户应用程序为了生产力通常使用Python编写,但其调用的NumPy库为了追求极致性能,其底层是由C和C++实现的。
异构计算是结合不同类型的处理器(如CPU和GPU)协同工作,每种处理器专注于其擅长的执行类型。单个应用程序可以同时利用多个处理器,将计算密集型任务卸载到GPU,而控制和串行任务则由CPU处理。
例如,在一段C++代码中,可以通过调用GPU加速的cuBLAS库(如cublasSaxpy函数)来执行大规模并行计算,从而实现CPU和GPU的协同工作。
多Die(Multi-Die)异构设备是多晶片缩放阶段的核心概念。如下图所示,一个单一的多Die设备内部可以集成多种不同的处理单元(Die),并连接到不同类型的外部存储器,例如DDR内存和HBM(高带宽内存)。这种设计允许将不同功能的芯片集成在一个封装内,以实现更高的性能和效率。
Grace/Hopper超级芯片是多Die异构设备的一个具体实现。
Grace/Hopper超级芯片通过NVLink C2C(Chip-to-Chip)技术将NVIDIA Grace CPU和Hopper GPU紧密地连接在一起。这种集成架构旨在解决计算问题,正如幻灯片中引述的观点:“...计算不仅仅是芯片问题,它是一个软件和芯片问题。”
其关键架构和带宽规格如下:
- Grace CPU:连接到240 GB的CPU LPDDR5X内存,带宽为 500 GB/s。
- Hopper GPU:连接到96 GB的GPU HBM3内存,带宽高达 4000 GB/s。
- NVLink C2C:连接CPU和GPU的内部总线,提供 900 GB/s 的双向带宽。
- 高速I/O:CPU侧提供4个16x PCIe-5接口,总带宽为 512 GB/s。
- NVLink网络:GPU侧提供18个NVLINK 4接口,用于连接多达256个设备,总带宽为 900 GB/s。
通过NVLink网络,最多可以将256个Grace/Hopper超级芯片互连,构建大规模的计算集群。每个超级芯片还配备了100 GB/sec的Infiniband NDR400网络接口,用于与其他节点通信。
这种架构支持构建由多个Hopper GPU组成的高性能多芯片系统,如下图所示。
幻灯片同时展示了计算扩展的三个层次:
- Multi-die:在单个芯片封装内集成多个计算裸片。
- Multi-chip:在单个主板或模块上集成多个芯片。
- Multi-node:通过网络连接多个独立的计算节点(服务器)。
Grace/Hopper架构的一个核心特性是实现了CPU和GPU之间无缝的数据访问。
通过NVLink C2C,CPU和GPU可以实现对彼此物理内存的缓存一致性访问(Cache-coherent access)。
- Grace CPU读取Hopper内存:CPU可以将GPU内存中的数据取回至其L3缓存。当GPU内存中的数据发生变化时,CPU L3缓存中对应的缓存行会被置为无效(evict)。
- Hopper GPU读取Grace内存:GPU可以通过CPU L3缓存加载CPU内存中的数据。CPU和GPU都可以命中缓存中的数据。当CPU内存中的数据发生变化时,GPU缓存中对应的缓存行会得到更新(update)。
地址转换服务(Address Translation Service, ATS)是实现统一内存的关键。ATS为整个系统创建了一个单一的共享页表,使得CPU和GPU可以完全访问彼此的内存分配。通过NVLink C2C,处理器可以访问系统内的任何物理内存,而无需进行数据迁移。
在一系列算法和应用上,Grace/Hopper超级芯片的性能表现优于传统的x86 CPU搭配NVIDIA A100或H100 GPU的平台。如下图所示,在OpenFOAM、CP2K RPA、NAMD、CuCo以及Hash Join等多种工作负载下,Grace Hopper(绿色柱)均展现出显著的相对性能优势。
计算的未来必然是多节点的。为了解决最大规模的问题,需要将成百上千个计算节点连接在一起,形成强大的计算集群。CUDA 平台通过其三个维度——语言、抽象层和规模——为这一挑战提供了全面的解决方案。
CUDA 并不仅仅是 CUDA C++。它是一个支持多种编程语言和 API 的综合性平台,旨在为 GPU 加速计算提供支持。
这些不同的语言和接口最终都汇集到底层的编译栈。
所有这些高级语言和接口都构建在一个统一的编译平台之上,该平台包括:
- NVVM / LLVM IR:一个基于 LLVM 的编译器中间表示,用于优化代码。
- PTX Assembly ISA:并行线程执行(Parallel Thread Execution)指令集架构,是 NVIDIA GPU 的一种稳定的汇编语言。
CUDA 不仅是一个语言平台,还是一个分层的抽象平台,开发者可以根据应用需求选择最合适的抽象层级。
这些抽象层级从底层到顶层包括:
CUDA 生态系统提供了一个广泛的选择谱系。开发者可以自由组合与匹配不同层级的语言、库、框架和SDK,为自己的应用选择最佳的抽象层级。
在多节点编程模型中,存在一个从追求更高生产力到追求更强控制力的权衡谱系。
不同的多节点编程模型位于这个谱系的不同位置:
沿此谱系的编程模型包括:
cuNumeric -> Legate -> Legion -> Multi-GPU Libraries -> NCCL -> CUDA-Aware MPI -> NVSHMEM
开发者需要根据应用需求,在生产力与控制力之间找到最合适的平衡点。
示例:cuNumeric (高生产力)
示例:NVSHMEM (强控制力)
多节点编程模型可以看作一个谱系,一端是更高的生产力,另一端是更强的控制力。这个谱系可以分为三种并行模式:
隐式并行的核心思想是,应用程序开发者使用顺序API,这些API可以映射到任何规模的系统上,从单个设备到大型集群,而无需修改应用程序代码。
Legate是一个为隐式并行设计的框架。应用程序通过顺序API调用Legate运行时。Legate框架主要由以下几部分组成:
通过Legate,支持Legate的库(Legate-Enabled Libraries)可以被Legate运行时隐式地扩展。
Legate启用的库采用基于任务的模型,其特点是没有显式同步和数据移动,因此它们之间是可组合的 (composable)。
Legate通过统一的数据抽象来实现库之间的可组合性。不同的任务通过映射同一个多维数组或“存储”(store)的分区来交换数据。Legate运行时会根据任务依赖关系自动复制或移动数据。
cuNumeric是基于Legate框架构建的NumPy API的隐式并行实现。它允许现有的NumPy应用程序在无需修改代码的情况下扩展到数千个GPU。
cuNumeric的算子(operator)可以分解为任务逻辑(Tasking logic)和计算任务(Computation tasks)。
性能表现:
cuNumeric的Beta版本于2023年3月发布。性能测试显示,cuNumeric在GPU数量从1个扩展到1024个时,其标准化吞吐量呈现出近线性的增长。
相关讲座: cuNumeric and Legate: How to Create a Distributed GPU Accelerated Library [S51789]
托管并行是多节点编程模型谱系中的中间地带。在这种模式下,应用程序通过调用可扩展的库或使用源代码标记来管理并行性,而具体的扩展工作则由运行时系统在后台处理。
NVIDIA提供了丰富的加速库,支持多GPU多节点环境。这些库分为:
* 主机库 (Host Libraries): 如cuBLAS, cuFFT, cuSOLVER, cuTENSOR, NPP, CURAND等。
* 设备库 (Device Libraries): 如cuFFTDx, cuBLASDx, CUDA Math API, CUTLASS等。
这些库涵盖了线性代数、稀疏矩阵运算、张量运算、求解器、随机数生成、图像处理、量子计算等多个领域。
该部分展示了 cuSOLVERMp 在 Selene SuperPOD 上的弱扩展性表现,并与 ELPA1 进行了比较。
测试配置:
性能:
弱扩展性测试结果:
cuSOLVERMp 相较于 ELPA1 的运行时间。cuSOLVERMp 在所有测试规模上都表现出更低的运行时间。cuSOLVERMp 的性能是 ELPA1 的 1.35 倍。该部分展示了 cuFFTMp 与 JAX 框架集成后的强扩展性性能。
JAX+cuFFTMp 和 cuFFTMp 的性能随着 GPU 数量从 8 个增加到 2048 个,求解时间显著下降,其扩展性表现紧密贴合了理想的缩放曲线。JAX+cuFFT(未使用 Mp 版本)的性能扩展性较差,求解时间下降缓慢。这凸显了 cuFFTMp 在多 GPU 环境下的优势。此页对比了 cuFFTMp 在 H100 和 A100 GPU 上的性能表现。
测试配置:
性能对比:
此图表展示了 H100-SXM GPU 相对于 V100 和 A100 在矩阵乘法(GEMM)方面的代际性能提升。
性能提升亮点:
结论: H100-SXM 在所有测试的数据类型上都展现了相对于前代产品(尤其是 A100)的显著性能飞跃。
NVIDIA Hopper 架构引入了对 FP8(8位浮点)数据类型的支持,cuBLASLt 库提供了实现 FP8 矩阵乘法的流程。
FP8 矩阵乘法流程:
op(A) 和 op(B) 通过 FP8 TensorOp 进行计算,内部累加精度为 fp32。scaleA、scaleB 相乘,并加上偏置项 C(已乘以其缩放因子 scaleC)。D_temp 应用融合操作(如激活函数等)。D_temp 的 amaxD 值,并乘以输出缩放因子 scaleD,最终将结果量化为 FP8 格式的输出 D。灵活性: 该流程也可以直接输出 fp16、bf16 或 fp32 格式的结果。
这一流程强调了“计算不仅仅是芯片问题,而是软件和芯片共同的问题”,即需要硬件(FP8 Tensor Core)和软件(cuBLASLt 等库)的协同才能发挥最大效能。
此页展示了使用 FP8 在大型语言模型训练和推理任务中带来的实际性能提升。
GPT-3 175B 训练(矩阵乘法):
BERT large 推理(预览):
注:推理性能是在一系列批处理大小和平均序列长度上测得的平均值。
NVIDIA 加速库分为主机库 (Host Libraries) 和设备库 (Device Libraries)。设备库可直接在 GPU 设备代码(Kernel)中调用,提供了更底层的编程灵活性。CUTLASS 是一个用于实现高性能矩阵运算的 C++ 模板库,是设备库中的一个关键组件。
CUTLASS 3.0 是一个面向 CUDA 的线性代数核函数张量核心编程模型。
主要特性:
CuTe 库重写,CuTe 是一种用于线程和数据布局的健壮表示方法。Hopper 架构支持:
CuTe 是 CUTLASS 3.0 引入的全新编程模型和 API,旨在简化和统一内存布局的表示。它通过 Layout<Shape, Stride> 的统一定义取代了旧有的复杂定义,可同时用于表示线程和数据的布局。
CUTLASS 3.0 通过简化但功能强大的核函数实例化,提升了开发体验。开发者可以通过修改单个参数来轻松切换 Hopper 优化的 GEMM 主循环调度策略。
CUTLASS 3.1(实验性)将引入 Python 接口,进一步降低使用门槛,实现从 Python 定义到与 PyTorch 等框架集成的自动化流程。
NVIDIA 提供了一套全面的 GPU 计算工具,帮助开发者在各个层面发现和解决问题。
compute-sanitizer,用于检查内存访问错误、未对齐访问、越界等问题。Nsight Systems 提供了强大的多节点分析功能,被称为“工具的工具”,用于处理大规模集群的性能数据。
该功能在 Nsight Systems 2023.2 版本中提供预览。其工作流包括设置与报告生成、启动分析、输出与可视化三个阶段。
这是一个多报告分析的应用实例。通过热力图,可以直观地展示多节点工作负载在一段时间内的行为,如内核时间覆盖率和 SM 活动,有助于快速识别性能瓶颈和不平衡现象。
数据安全通常关注静态数据(Data at Rest)和传输中数据(Data in Transit)。然而,第三种状态——使用中数据(Data in Use)——的保护通常较弱,构成了重大风险。
机密计算旨在解决“使用中数据”的保护问题,通过保护静态、传输中和使用中的数据,构成了端到端数据安全的关键一环。
机密计算关闭状态 (Confidential Computing: OFF): 在传统虚拟化环境中,Hypervisor(虚拟机监控程序)对所有系统内存和 GPU 内存拥有完全访问权限,数据传输是明文的。
机密计算开启状态 (Confidential Computing: ON): 通过在 CPU 上创建可信执行环境(Trusted Execution Environment, TEE),部署一个机密虚拟机(Confidential VM)。Hypervisor 被阻止访问机密虚拟机的系统内存和 GPU 内存,且 CPU 和 GPU 之间的数据传输是加密的。
本节通过一系列图示,分步阐述了标准的CUDA应用程序工作流,并将其与在保密计算(Confidential Computing, CC)环境下的工作流进行对比,强调了在启用保密计算后,CUDA应用程序无需修改即可运行。
在标准的非保密计算环境中,一个典型的CUDA应用程序执行包含以下五个步骤:
将数据从CPU复制到GPU:通过PCIe总线使用直接内存访问(DMA)将数据从CPU内存传输到GPU内存。
启动内核处理数据:在GPU上启动CUDA内核,对传输过来的数据进行计算。
将数据从GPU复制回CPU:计算完成后,通过DMA将结果从GPU内存传回CPU内存。
在保密计算环境中,CPU及其内存运行在一个受保护的保密虚拟机(Confidential VM)或可信执行环境(Trusted Execution Environment, TEE)内,而GPU则位于该环境之外。尽管环境发生了变化,CUDA应用程序的执行流程对开发者而言保持不变。
以下是在保密计算开启(CC On)的情况下,CUDA执行流程的对应步骤及其变化:
正常的GPU分配:与CC关闭时相同,在GPU内存中分配缓冲区。
受管分配与初始化:与CC关闭时使用锁页内存不同,CC开启时采用受管内存(Managed allocation)进行分配和初始化。数据位于受保护的CPU内存中。
加密的DMA传输:当数据通过PCIe总线从CPU传输到GPU时,传输过程是加密的,以保护数据在离开TEE后的机密性。
加密的内核启动:内核的启动指令和相关数据在传输和执行过程中也受到保护。
加密的DMA传输:计算结果从GPU传回CPU时,同样经过加密的DMA传输,确保结果数据在进入TEE之前保持机密。
核心优势在于,尽管底层增加了加密和解密等安全措施,但从开发者的角度来看,所使用的CUDA API(如cudaMalloc, cudaMemcpy, 内核启动语法)与标准环境完全相同,实现了应用程序代码的无缝迁移。