CUDA: New Features and Beyond
CUDA: New Features and Beyond
Stephen Jones, CUDA Architect | GTC 2025
摘要
本演示文稿首先明确了CUDA的定义,强调它不仅仅是CUDA C++,而是一个用于GPU加速的完整平台。接着,文稿回顾了CUDA平台的演进,从最初的基础组件(如cuFFT, cuBLAS, CUDA C++)发展到如今包含数百个框架、SDK、库和工具的复杂生态系统。通过以PyTorch为例,文稿阐述了CUDA平台的分层软件架构以及各层之间的互操作性,指出没有任何应用程序只使用单一层,而是混合搭配使用不同层的工具来平衡生产力与性能。最后,文稿指出了当前软件栈正变得越来越深,即时(JIT)编译和代码生成在几乎每个层面都变得至关重要,并提出优化是一个领域特定(Domain-Specific)的问题。
目录
- 1. CUDA 平台概述
- 2. 现代软件栈的挑战与优化
- 3. CUDA Python: 全栈式 GPU 加速
- 4. 高生产力的 Python 加速库
- 5. GPU 内核编程模型
- 6. cuTile:面向 CUDA 的瓦片编程
- 7. Pythonic GPU 编程生态与组合性
- 8. 扩展至数据中心规模
- 9. 附录
1. CUDA 平台概述
1.1. CUDA 平台的定义
- CUDA 不是 CUDA C++:演讲首先澄清一个常见的误解。
- CUDA 是 NVIDIA 的 GPU 加速平台:CUDA 是一个完整的平台,旨在为GPU加速提供全面的支持,而不仅仅是一种编程语言。
1.2. CUDA 平台堆栈的演进
最初的 CUDA
在早期,CUDA平台相对简单,主要由以下几个核心部分组成:
- 加速库 (Accelerated Libraries): 如 cuFFT, cuBLAS。
- 内核编写 (Kernel Authoring): 主要使用 CUDA C++。
- 编译器堆栈 (Compiler Stack): nvcc。
- 主机运行时与工具 (Host Runtimes & Tools): CUDA Runtime。
当今的 CUDA 平台堆栈
如今,CUDA平台已经发展成为一个极其丰富的生态系统,包含了数百个框架、SDK、编译器、库、语言、领域特定语言(DSL)和运行时。
- 框架 & DSLs (Frameworks & DSLs): TensorRT, Omniverse, JAX, PyTorch
- SDKs: RAPIDS, CUDA-Q, BioNeMo, Ariel
- 领域特定库 (Domain-Specific Libraries): cuQuantum, CUDA-CV, cuDNN, nvComp
- 加速库 (Accelerated Libraries): Thrust, cuBLAS, cuFFT, NPP
- 通信库 (Communication Libraries): NCCL, NVSHMEM, MPI, UCX
- 设备库 (Device Libraries): CUB, CUTLASS, cuBLASDx, libcu++
- 内核编写 (Kernel Authoring): CUDA C++, PTX, OpenCL, CUDA Fortran
- 编译器堆栈 (Compiler Stack): nvcc, nvrtc, nvptx, ptxas
- 主机运行时与工具 (Host Runtimes & Tools): CUDA Runtime, Drivers, Nsight Tools, Installers
1.3. 分层架构与互操作性
所有软件都是分层的,开发者需要选择能够平衡生产力(productivity)和性能(performance)的合适层次进行开发。
以PyTorch为例,一个高层次的深度学习框架依赖于CUDA堆栈中的多个底层组件:
- PyTorch(框架层)调用 cuDNN 和 cuBLAS(领域特定库和加速库)。
- cuBLAS 进一步依赖于 CUTLASS(设备库)。
- CUTLASS 等库的底层实现则依赖于 CUDA C++(内核编写层)。
- CUDA C++ 代码通过 nvcc(编译器)进行编译。
- 最终所有操作都通过 CUDA Runtime(主机运行时)在GPU上执行。
互操作性是CUDA平台的核心
没有任何应用程序只使用堆栈中的某一个层。CUDA平台的核心价值在于其互操作性(Interoperability),允许开发者根据需求混合和匹配不同层次的工具。这使得用户可以根据特定任务的需求,使用最合适的工具集。
2. 现代软件栈的挑战与优化
2.1. 软件堆栈的深化与即时编译 (JIT)
软件堆栈日益加深
现代应用,特别是深度学习应用,其软件堆栈正变得越来越深。一个典型的深度学习应用可能经历以下层次:
Deep Learning Application -> TensorRT/PyTorch/JAX -> cuDNN -> cuBLAS -> CUTLASS -> CUDA C++ -> NVVM/LLVM -> PTX
代码生成成为常态
随着堆栈的加深,代码生成(Code Generation)正在成为常态。编译过程本身也变成了一个多阶段的堆栈:
TensorRT, Inductor, XLA -> Graph JIT -> JIT LTO -> cpp / Triton IR -> nvcc -> nvptx -> ptxas
JIT 编译遍布各个层级
即时编译(JIT Compilation)几乎出现在软件堆栈的每一个层级。从上层的框架到底层的库,许多组件都依赖于语言和领域特定语言(DSL)编译器在运行时生成和优化代码。
2.2. 优化的本质:领域特定与分层
优化是一个领域特定的问题 (Optimization is a Domain-Specific Problem)。这意味着最佳的优化策略高度依赖于具体的应用领域和问题背景。
不同的领域具有不同的计算模式和架构,需要针对性的优化策略。
- 推荐系统 (Recommender System):通常涉及数据处理、特征工程、模型训练和推理等多个阶段的复杂流程图。
- 图神经网络 (Graph Neural Network):处理非结构化数据,其计算模式涉及节点间的消息传递和聚合。
- 大语言模型 (Large Language Model):以 Transformer 架构为核心,包含大量的矩阵运算和注意力机制。
这些领域特定问题也延伸到深度学习网络、科学计算和图形学等多个方面,每个领域都有其独特的优化挑战和方法。
优化是一个分层问题。不存在通用的全局优化器。优化需要在计算堆栈的多个层次上进行,从高层的模型并行到底层的指令调度。
- 模型范畴 (Model scope):关注并行化与分布式执行。
- 操作范畴 (Operation scope):关注调度与内存管理。
- 核函数范畴 (Kernel scope):关注任务和集合操作。
- 函数范畴 (Function scope):关注指令调度。
整个软件栈,从框架和DSL到主机运行时和工具,都提供了优化的机会。不同层级之间可以混合搭配,具有互操作性。
2.3. JIT 编译性能与开发者工具
软件栈的每一层都有编译器
软件栈的每一层都有不同的优化机会,这需要一个端到端的编译器栈来协同工作。这个编译器栈与软件栈的各个层级(如框架、SDK、库、运行时等)进行交互,实现代码生成和优化。
JIT 编译性能即应用性能
当编译器处于关键路径上时,编译时间就变得至关重要。
-
--fast-compile特性:Max: 最大程度地减少编译时间,但运行时代码较慢。Mid: 在编译时间和执行速度之间取得平衡。Min: 最小程度地减少编译时间,代码执行速度更快。
这个特性适用于离线编译 (nvcc) 和即时编译 (JIT)。
-
运行时编译 (NVRTC) 缓存:
- NVRTC 现在可以透明地缓存编译结果。
- NVRTC 现在支持预编译头文件 (PCH),从而提高编译速度。
- 缓存命中可以使 PTX/二进制文件的生成速度比以前快 100 倍。
编译器工具即开发者工具
当编译成为执行的一部分时,我们需要工具来分析编译过程。
-
编译时间追踪 (Compile Time Tracing):
编译器可以生成“火焰图”,详细展示源代码中哪些元素在编译时耗时最长。 -
编译时间顾问 (Compile Time Advisor) (即将推出):
- 分析编译器追踪工具的输出,并生成关于“昂贵”模板和头文件的摘要报告。
- 生成关于使用哪些编译器标志来加速编译的建议。
3. CUDA Python: 全栈式 GPU 加速
3.1. GPU 加速需要一个平台
GPU 加速不仅仅是硬件,它依赖于一个完整的软件平台,涵盖了从底层到高层的各个方面。
- 框架 & DSLs: TensorRT, Omniverse, JAX, PyTorch
- SDKs: RAPIDS, CUDA-Q, BioNeMo, Ariel
- 领域特定库: cuQuantum, CUDA-CV, cuDNN, nvComp
- 加速库: Thrust, cuBLAS, cuFFT, NPP
- 通信库: NCCL, NVSHMEM, MPI, UCX
- 设备库: CUB, CUTLASS, cuBLASDx, libcu++
- 内核编写: CUDA C++, PTX, OpenCL, CUDA Fortran
- 编译器栈: nvcc, nvrtc, nvptx, ptxas
- 主机运行时 & 工具: CUDA Runtime, Drivers, Nsight Tools, Installers
3.2. CUDA Python 全平台栈
为了在 Python 中实现高效的 GPU 加速,需要提供一个同样覆盖整个技术栈的解决方案,这就是 CUDA Python。它为 NVIDIA 的 GPU 加速平台提供了全面的 Python 接口。
无论您需要针对技术栈的哪个层级,都可以通过 Python 来实现。CUDA Python 为从框架到主机运行时的每一层都提供了相应的 Python 库和工具。
CUDA Python 是一个完整的平台,所有层级必须协同工作。它支持不同层级之间的互操作性,允许开发者混合和匹配各个组件以满足其特定需求。
CUDA 与 Python:光速般的生产力故事
这是一系列关于 CUDA Python 的讲座安排,旨在引导开发者逐步掌握使用 Python 进行 GPU 编程。
- 第0步: 听我们的 Python 故事
- 加速的 Python:社区与生态系统
- 星期二, 3月18日, 3:00 PM - 3:40 PM PDT
- 第1步: 学习 CUDA Python 工具
- CUDA Python 开发者工具箱
- 星期三, 3月19日, 10:00 AM - 10:40 AM PDT
- 第2步: 深入探索内核
- 在 Python 中编写 CUDA 内核的 1001 种方法
- 星期三, 3月19日, 11:00 AM - 11:40 AM PDT
- 第3步: 精通 Tensor Core
- 使用 CUTLASS 4.0 启用 Tensor Core 编程
- 星期五, 3月21日, 11:00 AM - 11:40 AM PDT
3.3. CUDA Python 核心组件:cuda.bindings 与 cuda.core
CUDA Python 的核心理念是它不仅仅是 C++ API 的简单转译。它提供了符合 Python 语言习惯的接口和工具。特别是在主机运行时与工具层,cuda.bindings 和 cuda.core 是其基石。
cuda.bindings
cuda.bindings 位于技术栈的底层,为底层的 CUDA C API 提供了低级别的、1:1 的 C 到 Python 的绑定。它直接与 CUDA API 和运行时编译器交互。
cuda.core - 符合 Python 风格的 CUDA 运行时
cuda.core 是一个构建在 cuda.bindings 之上的高级 Pythonic 对象模型,为设备、程序编译与执行、链接器及二进制工具等提供了封装。它使得开发者无需直接编写 C++ 代码。
其 GitHub 地址为: https://github.com/NVIDIA/cuda-python
cuda.core 的完全进程内执行流
使用 cuda.core,整个执行流程都在 Python 进程内部完成,无需调用外部编译器。
- Python 源代码文件 (
x.py) 由 Python 解释器处理。 - CPU Python 代码正常执行。
- 用户定义的 GPU 内核(可以是 C++ 或 Python 字符串形式)通过 NVRTC Python 运行时进行即时编译。
- 通过
cuda.core.launch等接口,将编译好的内核在 GPU 上启动执行。
3.4. 加速的 Python 开发者工具
软件开发离不开开发者工具。NVIDIA 为 Python 开发者提供了一系列加速工具。
NVTX & Nsight Tools for Python
- NVTX 注释: 支持 Python 源代码的 NVTX (NVIDIA Tools Extension) 注释,允许开发者在代码中标记特定的范围或事件,以便在性能分析工具中进行可视化。
- Nsight 工具: 支持 Python 调用栈的分析,帮助开发者理解 Python 代码与底层 CUDA 操作之间的关联。
- Python CUPTI 绑定: 为 CUDA Python 应用程序提供分析文件的创建能力。
- JupyterLab 集成: 与 JupyterLab 环境无缝集成。
- GIL 分析: 支持对 Python 全局解释器锁 (Global Interpreter Lock) 的性能分析。
- 框架级支持: 为包括 PyTorch 在内的深度学习框架提供层级(模块)的性能分析支持。
上图右侧展示了 Nsight Tools 的可视化界面,其中清晰地显示了 Python 函数(如 my_function)的执行时间线(红色和蓝色条),以及其内部的 CUDA 操作。
4. 高生产力的 Python 加速库
4.1. 无需更改代码即可实现 Python 加速
了解 GPU 编程的第一件事是,你可能根本不需要进行任何 GPU 编程。NVIDIA 提供了丰富的库和工具,可以在不改变或极少改变代码的情况下,利用 GPU 的强大算力。
NVIDIA 的 Python 生态系统涵盖了从底层运行时到顶层框架的多个层次,包括:
- 框架与领域特定语言 (DSLs): TensorRT, Omniverse, Warp
- 软件开发工具包 (SDKs): RAPIDS, CUDA-Q, Holoscan
- 领域特定库: cuPyNumeric, cuDNN-python
- 加速库: cuda:parallel, nvmath-python
- 通信库: mpi4py, nvshmem4py
- 设备库: cuda.cooperative, nvmath-python
- 内核编写: numba-cuda, cuTile, CUTLASS
- 编译器栈 和 主机运行时与工具: cuda:bindings, cuda:core, Nsight Tools
4.2. cuPyNumeric:零代码更改的扩展
cuPyNumeric 旨在实现从单 CPU 核心到拥有数千个 GPU 的多 GPU 超级计算机的零代码更改扩展。
cuPyNumeric 的核心特性:
- 目标用户: 非常适合领域科学家和研究人员。
- 易用性: 用户可以用 Python 和 NumPy 编写代码,并将其无缝扩展到数千个 CPU 或 GPU 上运行。
- 兼容性: 它是 NumPy 的直接替代库 (drop-in replacement),并能与 SciPy 及其他 PyData 生态系统中的库协同工作。
- 零代码更改: 如下方代码示例所示,实现 GPU 加速和分布式计算,通常只需将 import numpy as np 更改为 import cupynumeric as np。
# 零代码更改扩展 NumPy 程序
import numpy as np
#size = 100000
size = 100000 * 100000
import cupynumeric as np
size = 100000 * 100000
A = np.random.randn(size, size)
B = np.random.randn(size, size)
C = A @ B
4.3. nvmath-python:高性能数学库
NVIDIA 提供了一套面向高性能 GPU 库的 Pythonic 接口,即 nvmath-python。
nvmath-python 位于 NVIDIA 加速计算生态的“加速库”层,为 Python 开发者提供了直接访问底层高性能数学计算库的能力。
nvmath-python 详解
nvmath-python 是一个为加速 Python 提供高性能 GPU 数学库的 Pythonic 接口。
重构 Python 数学库的理念:
- Pythonic APIs: 提供为峰值性能而设计的 Python 风格接口。
- 即时编译 (JIT): 支持用于核函数融合 (kernel fusion) 的即时编译。
- 可扩展性: 无需大规模代码重写即可实现扩展。
- 开源与互操作性: 开源,并能与现有生态系统互操作。
- 获取方式: 可通过 Conda、Pip 和 GitHub 获取。
nvmath-python: API 设计与集成
nvmath-python 提供了无状态 (Stateless) API 以方便使用,同时提供有状态 (Stateful) API 以实现峰值性能。
- API 设计:
- 无状态 API: 调用方式简单直接,适合快速实现功能。如下代码所示,直接调用
nvmath.linalg.advanced.Matmul(a, b)。 - 有状态 API: 通过创建计划 (plan) 并执行的方式,可以获得更高的性能,适用于性能敏感的场景。
- 无状态 API: 调用方式简单直接,适合快速实现功能。如下代码所示,直接调用
- 互操作性: 能与其他张量库和框架(如 PyTorch)无缝协作。
- 自定义内核: 为自定义内核编写者提供设备代码绑定,可与
numba-cuda和NVIDIA Warp集成。
nvmath-python: 即时编译 (JIT) 与全 Pythonic 体验
nvmath-python 致力于提供完整的 Pythonic 体验,支持用于核函数融合的即时编译。
- 全 Pythonic 体验:
- 代码中不再需要嵌入 CUDA C++ 字符串。
- 依赖 GPU 原生 (nvrtc) 和 Python (Numba, Warp) 的 JIT 编译器。
- 同时提供主机 (host) 和设备 (device) API。
- 广泛的后端支持:
- 主机绑定支持用于 Grace CPU 的 NVIDIA CUDA 数学库和性能库,以及用于 x86 CPU 的 MKL。
- 代码示例: 下图展示了一个 Python 函数 (
user_defined_code) 作为回调函数,在执行 FFT (快速傅里叶变换) 的epilog阶段被即时编译和调用。
# Python function implemented callback, compiled just-in-time
def user_defined_code(data_out, offset, data, filter_data, unused):
data_out[offset] = data * filter_data[offset] / N
epilog = nvmath.fft.compile_epilog(user_defined_code, "complex128", "complex128")
r = nvmath.fft.fft(a, axes=[-1], epilog=("tostr", epilog, "data": filter_data.ptr))
nvmath-python: 无缝的可扩展性
nvmath-python 提供一致的 API,适用于 CPU 和 GPU 执行空间,以及单 GPU 和多节点环境,实现了无需大规模代码重写的可扩展性。
- 支持 CPU 执行: 通过 NVPL (aarch64) 和 MKL (x86) 支持 CPU 执行空间。
- 与现有库互操作: 可与 NumPy, CuPy, PyTorch 等现有张量库无缝集成。
- 跨 GPU 扩展: 能够扩展到单 GPU 之外,在多 GPU 环境下达到峰值性能。
应用案例:南希·格雷斯·罗曼空间望远镜
nvmath-python 在实际科研项目中展示了强大的加速能力,例如在用于超新星探测的 PHROSTY 发现与光度测量流水线中。
该应用包含三个部分:
1. 预处理: 计算点扩散函数。
2. sFFT: 应用傅里叶变换并寻找图像间的差异。
3. 后处理: 寻找并应用去相关函数。
PHROSTY 增量加速效果:
与纯 NumPy 实现(基线 1x)相比:
- 使用 CuPy 替代 NumPy 进行 GPU 加速,获得了 23倍 的速度提升。
- 在 CuPy 的基础上,进一步集成 nvmath-python 进行优化,最终获得了 39倍 的速度提升。
这是一个由杜克大学、匹τ堡大学、卡内基梅隆大学和劳伦斯伯克利国家实验室合作的研究项目。
4.4. cuda.parallel 与 cuda.cooperative:简单易行的高性能内核
NVIDIA 提供了 Pythonic 的并行算法库,让编写高性能内核变得更加简单。
cuda.parallel 和 cuda.cooperative 是实现这一目标的关键库,它们分别位于加速库和设备库层。
这两个库为 Python 开发者提供了不同粒度的并行算法。
cuda.parallel:- 在主机代码 (host code) 中调用,作用范围是整个 GPU。
- 在 Python 中提供基础的并行算法,实现 GPU 加速而无需深入 C++。
- 基于 C++ 的
cuda::thrust并行算法库构建。
cuda.cooperative:- 在设备代码 (device code) 中调用,作用于一个 warp 或 block 内部。
- 为
numba-cuda内核编写者提供基础算法。 - 基于 C++ 的
cuda::CUB协同设备库构建。
从加速的 Python 中获得 C++ 级别的性能
cuda.parallel 和 cuda.cooperative 将 Thrust 和 CUB C++ 库直接链接到 Python 代码中,从而实现了接近原生 C++ 的性能。
- 性能对比: 上图左侧的柱状图显示了分段排序 (Segmented Sort) 任务中,使用
cuda.parallel和cuda.cooperative的 Python 实现与直接使用 Thrust 和 CUB 的 C++ 实现的性能对比。结果表明,Python 实现的相对时间非常接近 C++ 的基线(1.0),证明其性能几乎无损。 - 执行模型:
- 串行 (Serial): 一个线程调用算法,一个线程执行算法。
- 并行 (Parallel): 一个线程调用算法,多个线程执行算法。
- 协同 (Cooperative): 多个线程调用算法,多个线程执行算法。
5. GPU 内核编程模型
NVIDIA 生态系统支持在 Python 中原生编写 GPU 内核。
内核编写层提供了多种工具:
- numba-cuda: 一个 JIT 编译器,可以将 Python 代码子集编译为 CUDA 内核。
- cuTILE: 用于编写高性能 tile-based 内核的库。
- CUTLASS: NVIDIA 的 CUDA C++ 模板库,用于实现高性能矩阵乘法及相关计算,其功能也可以通过 Python 接口访问。
5.1. 并行化基础:从数据到线程
GPU 并行处理始于一个大型数据数组。
以一张图片为例,它可以被看作一个像素数据数组,这是并行处理的起点。少量的并行化可以释放巨大的性能潜力。
第1步:分而治之 (Divide and Conquer)
为了让 GPU 能够同时处理多个数据片段,需要将数据分解成图块(tiles)。将数据(如一张图片)分割成多个图块,然后启动一个块网格(Grid of Blocks)来并行处理这些图块。
每个流式多处理器(SM)都同时运行线程块(Blocks of Threads)。每个块将处理一个或多个数据图块。
第2步:将数据分配给每个线程
每个线程获得不同的数据,但运行相同的程序。应用程序将数据映射到每个块中的线程上。这构成了线程级模型 (Thread-Level Model):
* 数据单元是单个元素。
* 执行单元是单个线程。
5.2. 执行模型的层次结构
网格级并行 (Grid-Level Parallelism)
对于许多应用来说,网格级并行是一种简单且高效的模型,通常也是开发者需要考虑的终点。
- 模型描述:
- 将相同的操作应用于一个大型数据数组,可以获得简洁的代码和高性能。
- 数据单元是一个数组(1D, 2D, 3D, ...)。
- 执行单元是整个 GPU。
- 编程模型:
- 许多现代计算框架和库都采用这种模型,例如:PyTorch, NVIDIA Warp, Matlab, JAX, cuPyNumeric。
线程级并行 (Thread-Level Parallelism)
这种执行方式被称为 SIMT (Single Instruction Multiple Thread,单指令多线程)。
SIMT 编程的特点:
* 程序结构是单线程的。
* 更易于编写和调试。
* 允许条件逻辑。
* 允许数据依赖的执行。
* 避免了向量-SIMD选择/掩码。
并行性通过将线程分组到块(Blocks)中来实现。这允许高效的批量并行执行和细粒度的工作。将线程级并行的实现交给编译器,通常可以获得比手动实现更高的性能。
三种执行模型对比
存在三种不同层次的执行模型:
- 网格级模型 (Grid-level models):
- 轻松加速批量数据操作。
- 编译器将数据映射到块和线程。
- 块级模型 (Block-level models):
- 为基于数组的程序提供生产力和性能。
- 应用程序将数据映射到块。
- 编译器将块映射到线程。
- 线程级模型 (Thread-level models):
- 为所有并行工作负载提供完全控制。
- 应用程序将数据映射到块和线程。
6. cuTile:面向 CUDA 的瓦片编程
6.1. 瓦片编程:块级并行
这种方法提供了像线程级那样的细粒度控制,但代码像网格级一样简单。它为基于数组的程序提供了更简洁的代码和更高的性能。
块级模型 (Block-Level Model):
* 数据单元是一个图块(Tile),可以是1D、2D、3D等。
* 执行单元是一个线程块(Block of threads)。
6.2. cuTile 简介
cuTile 即将登陆 CUDA Python,随后是 CUDA C++。
瓦片编程 (Tile Programming) 是一种在规则的数据瓦片上进行块内协作执行的方式。
* 数据和操作的粒度是数组/张量。
* 非常适合规则/数据并行问题。
* 允许简单且高性能的核函数融合(kernel fusion)。
* 通过隐式使用线程来简化数组操作。
下图展示了瓦片张量加法(数组粒度)与SIMT张量加法(元素粒度)的对比。
基于数组/张量的瓦片模型可以高效地映射到 Tensor Cores,简化了代码结构,使其更容易实现高性能。
* 编译器会自动管理内存空间并映射到 Tensor Core 硬件。
* cuTile 程序在当前和未来的 Tensor Cores 代际之间是可移植的(但可能需要重新调优以达到峰值性能)。
6.3. cuTile 的特性与代码风格
cuTile 在 CUDA Python 平台栈中的位置
cuTile 是 CUDA 平台的一个新的核心组件,位于内核编写(Kernel Authoring)层,与 numba-cuda 和 CUTLASS 并列。
cuTile 可以在任何支持 CUDA 的地方工作
- cuTile 扩展了 CUDA:
- 作为 CUDA 平台的新核心组件。
- 保证了所有 CUDA 的稳定性、兼容性和可移植性。
- 全面支持 Windows、Linux 等。
- 即将登陆 Python,然后是 C++。
- cuTile 内核就是 CUDA 内核:
- 可以在任何可以使用普通内核的地方工作,例如在 PyTorch、CUDA Graphs 等中使用。
- 拥有完整的生态系统支持:开发工具、JIT/离线编译等。
- 适用于 Ampere 及更新的 GPU 架构。
cuTile 是更简洁的 CUDA
瓦片编程简化了广泛的应用:
* 适用于任何处理规则数组或数据并行问题的程序。
* 更容易实现峰值性能。
* 提供了一种稳定、可移植的方式来编程 Tensor Cores。
* 它只是 CUDA 的一部分——可以与所有东西协同工作。
cuTile 内核是 CUDA 内核,可以在一个工作流中同时使用 Tile 和 SIMT 内核。
* 初始版本将提供 Tile kernel 和 SIMT kernel。
* 后续版本将提供 Hybrid kernel(混合内核)。
cuTile 是 Python 风格的 CUDA
瓦片编程的设计对 Python 开发者非常直观。
* 基于数组的模型在 Python 中很常见(例如 NumPy)。
* cuTile 程序每个块只有一个逻辑控制线程。
* 操作是隐式协作和自动并行的。
下面的代码对比了 NumPy 实现的 Softmax 和 cuTile 实现的 Softmax,展示了其相似的编程模型。
6.4. 应用案例与性能
下图比较了三种矩阵乘法算法的实现:Numba SIMT、cuTile-python 和 cuTile-C++,展示了 cuTile 在简化代码方面的优势。
在 cuTile 中实现的 Llama-3.1
下图展示了使用 PyTorch 和自定义核函数进行 Llama-3.1 推理的实现。左侧是 Llama-3.1 模型的架构图,右侧的性能图表显示了在 Blackwell B200 平台上,不同 PyTorch 后端的 Meta-Llama-3.1-8B 推理性能与 cuTile 的相对比较。与 Torch Eager Flash SDP(0.41x)相比,cuTile(0.93x)的性能显著提升,接近于 Torch Eager cuDNN SDP(1.00x)的峰值端到端性能。
兼顾高生产力与高性能
cuTile 旨在以更简单的代码和更短的时间,实现接近于手动调优的 cuDNN 的性能。如下图所示,cuTile 相比 cuDNN,在开发上投入更少、代码行数更少、实现时间更短,并且完全在 Python 中完成,其性能可以达到手动调优 cuDNN 的 90% 以上。
cuTile 中的计算物理学
cuTile 的应用不仅限于深度学习,还可用于计算物理学领域。下图展示了使用 "Miniweather" 2D 粘性流体流动模拟微应用实现的几个计算物理学场景,包括碰撞热流(COLLIDING THERMALS)、注入(INJECTION)、密度(DENSITY)和上升热流(RISING THERMAL)。
6.5. Tile IR:新的编译器目标
软件开发生态的每一层都离不开相应的开发者工具。cuTile 作为内核编写工具,与 Nsight Tools 等性能分析工具紧密联系。
NVIDIA Nsight Systems 等开发者工具可用于对 cuTile 内核进行深入的性能分析和优化。下图展示了使用 Nsight 对前述 Llama3 推理工作负载进行追踪分析的界面,可以清晰地看到 GPU 吞吐量、内核执行时间线以及 Python 代码的回溯栈,帮助开发者定位性能瓶颈。
cuTile 不仅是开发者编写高性能内核的工具,也是上层框架和语言编译器的目标。诸如 TensorRT、PyTorch、JAX 等框架,以及 cuDNN、cuBLAS 等库,都可以通过语言和领域特定语言(DSL)编译器将计算任务生成并调度到 cuTile 上执行。
为了更好地支持像 cuTile 这样的基于 Tile 的编程模型,NVIDIA 引入了一种新的底层编译器中间表示(Intermediate Representation)——Tile IR。如下图所示,cuTile 程序通过 "Tile path" 编译到 Tile IR,而传统的 SIMT 程序则继续沿用 "SIMT path" 编译到 NVVM/LLVM 和 PTX。最终,两者都会被编译成 GPU 可执行文件。
可执行二进制文件可以同时包含 Tile IR 和 PTX 代码,并在新的 GPU 架构上自动运行。基于线程的(SIMT)内核和基于 Tile 的内核可以无缝共存,既可以离线编译存储在磁盘上,也可以在运行时进行即时编译。
7. Pythonic GPU 编程生态与组合性
NVIDIA 软件栈的多个层次都提供了原生的 Python 接口,用于 GPU 内核的编写和加速。如下图所示,从上层的框架(PyTorch, Triton, Warp)到设备库(cuda.cooperative, nvmath-python),再到内核编写层(numba-cuda, cuTile)以及编译器栈(Tile IR),都为 Python 开发者提供了丰富的工具。
7.1. 组合性:互操作性是核心要求
在实际应用中,通常需要使用不同的工具来构建应用的不同部分,并将它们组合在一起。如下图所示,NVIDIA 生态系统中的各种工具(如 PyTorch, Warp, cuTile, CUTLASS 等)可以相互协作,共同构建复杂的“模拟 + AI”应用。
nvmath-python 库在组合性中扮演了重要角色。它在加速库(Accelerated Libraries)层面提供了 Pythonic 的主机 API,同时在设备库(Device Libraries)层面提供了可内联到内核中的块级设备 API,从而实现了主机端和设备端代码的无缝衔接。
下图进一步说明了不同 Python 工具如何协同工作:
- Warp:一个用于编写 GPU 加速和可微内核的 Python DSL 和框架。
- numba-cuda:支持在 Python 中进行原生的 CUDA SIMT 编程。
- nvmath-python:提供可内联到内核中的块级设备 API,用于加速数学库。
这些工具共同构成了强大的 Python GPU 编程生态系统。
加速数学库(如 nvmath-python)可以通过不同的 API 暴露给软件栈的不同层级。上层框架如 Warp 可以通过可微算子来使用其功能,而底层内核编写工具如 numba-cuda 或 Tile IR 可以直接从内核中调用库的 API。
尽管通过更高层次的抽象(如 numba-cuda 和 Warp)来调用底层库,性能却几乎没有损失。下图展示了在 A6000 GPU 上使用 nvmath-python 设备 API 进行 FFT 卷积的性能对比。结果显示,numba-cuda(45.3 ms)和 Warp(47.9 ms)的性能与原生 CUDA C++(45.5 ms)的性能相当。
7.2. NVIDIA Warp 框架
NVIDIA Warp 是一个能够轻松编写 GPU 加速和可微内核的框架,可用于扩展深度学习模拟流程。其主要特性包括:
- 基于内核的编程范式,非常适合模拟和几何处理。
- 支持反向模式自动微分,可自动为每个内核生成反向传播版本。
- 与深度学习框架的高效互操作性,为结合模拟与 AI 方法提供了灵活性。
Warp + Warp Tile:桥接网格级和块级模型
Warp 和 Warp Tile 旨在结合模拟和 AI 方法。
- Warp Tile:
wp.tile()函数由块(block)中的所有线程协同执行。- 用于在 Warp 中实现神经网络层,能够融合现有工作负载。
- 结合了细粒度的模拟与 AI,并支持使用块级加速的
nvmath-python库操作。 - 一个应用案例是使用一个小型融合多层感知机(MLP)网络来近似二维流体模拟的图像。下图展示了原始图像和经过约1分钟训练的4层MLP的输出结果。
更多信息和示例,可参考博客文章《Introducing Tile-Based Programming in Warp 1.5.0》。
7.3. 原生 Python Tile-Based 编程工具
当前不存在适用于所有应用场景的单一最优工具。NVIDIA 提供了丰富的 CUDA Python 开发者工具箱,涵盖从底层编译器到顶层框架的多个层面。
下图展示了不同层级的工具和库,其中高亮了支持 Tile-Based 编程的组件,如 OpenAI Triton, Warp Tile, cuda.cooperative, nvmath-python, cuTENSOR, 和 Tile IR。
开发者可以根据应用需求选择最合适的工具:
- OpenAI Triton:块级(Block-level)DSL,专为自定义大语言模型(LLM)和高性能核函数生成而设计。
- Warp Tile:块级 Warp,结合了自动微分和块并行操作。
- cuTENSOR (CUTLASS):将 CUTLASS 引入 Python,为张量核心(tensor cores)的各个方面提供了最大程度的控制。
- Tile Programming in CUDA:用于 GPU 计算的块级编程模型。
7.4. CUTLASS 4.0:C++的性能与Python的生产力
CUTLASS 4.0 旨在将 C++ 的高性能与 Python 的高效率开发体验相结合。
CUTLASS Python 的主要特性包括:
- 在 Python 中实现完整的设备端可编程性。
- 极大改善的调试体验。
- 与 C++ 版本功能完整匹配,且性能相当。
- 与 C++/nvcc/nvrtc 编译相比,显著减少了编译时间。
- 提供从基础到高级实现的渐进式复杂性级别。
- 提供一流的文档支持。
CUTLASS Python 是基于共享的底层 IR 栈构建的,与 Tile IR 协同工作。
性能对比
实验证明,CUTLASS Python 版本的性能与 C++ 版本几乎没有差距。在 GEMM MNK=8k, FP16, B200 的测试中,Python 版本的性能达到了 C++ 版本的 99%。
编译时间对比
CUTLASS Python 的即时编译(JIT)时间远低于 C++。在相同的 GEMM 测试中,C++ 版本的编译时间为 25842 毫秒,而 Python 版本仅为 180 毫秒,速度提升超过 100 倍。
8. 扩展至数据中心规模
加速计算的范围正在不断扩大,从单个 GPU 芯片,扩展到单个计算节点(服务器),乃至整个数据中心规模。
8.1. CUDA DTX:CUDA 分布式执行
为了应对数据中心规模的挑战,NVIDIA 推出了 CUDA DTX (CUDA DisTributed eXecution),旨在实现全尺度的 CUDA 计算。CUDA DTX 是一个低延迟、异步的分布式运行时。
计算统一设备架构(Compute Unified Device Architecture)
在当前的单节点环境中,CUDA 架构包含两个关键要素:统一机器模型(Unified Machine Model)和统一运行时(Unified Runtime)。
- 统一机器模型:为所有硬件组件提供一个通用的视图,向上层应用抽象硬件细节。
- 统一运行时:为所有硬件组件提供一个通用的接口,向下管理硬件资源。
CUDA DTX 对 CUDA 的扩展
CUDA DTX 将 CUDA 扩展至全尺度,提供了一个机器抽象。它同样包含两个关键要素:可扩展的分布式机器模型和分布式运行时。
-
分布式机器模型 (Distributed Machine Model):
- 为整个数据中心规模的资源提供扁平命名空间。
- 支持拓扑感知的执行。
- 提供弹性和虚拟化的资源。
-
分布式运行时 (Distributed Runtime):
- 完全异步的执行模型。
- 动态、可控的调度机制。
- 分布式资源管理。
- 分布式通信。
8.2. Nsight Cloud:大规模云原生工具与分析
Nsight Cloud 提供了当今可用的云原生工具和大规模分析能力。
-
数据中心规模的易用性:
- 减少了对自定义调试构建或容器的需求。
- 可在数千个节点上运行。
- 简化了大规模收集数据的分析和呈现。
-
为云用户改进的横向扩展能力:
- 支持多节点通信。
- 集成作业调度器/任务编排器。
下图展示了 Nsight Cloud 在 Kubernetes 集群中的架构,包括 Nsight Operator, Injector, Coordinator 以及在工作节点上的 Nsight Streamer 和 Nsight Analyzer 等组件。
8.3. cuda-checkpoint:GPU的检查点与恢复
cuda-checkpoint 是一个用于GPU的检查点(Checkpoint)和恢复(Restore)的实用工具。其工作流程如下图所示:应用程序从“开始”(Start)执行计算(Compute),在每N步之后,可以创建一个“检查点”(Checkpoint)将状态保存到磁盘。之后,可以从这个检查点“重启”(Restart)应用程序。此外,也可以强制触发检查点。
主要特点:
- 无需对应用程序进行任何插桩(instrumentation):
1. 程序执行在GPU和CPU上都会被暂停。
2. 状态被写入磁盘。
3. 之后可以恢复并取消暂停。
- 命令行和API级别的工具:
- 将GPU状态保存和恢复到CPU内存中。
- 与Linux的“CRIU”(Checkpoint/Restore In Userspace)工具协同工作。
- cuda-checkpoint 可在GitHub上获取。
- 使用示例:
$ cuda-checkpoint -action checkpoint
8.4. GPU 进程迁移
利用检查点技术,可以实现GPU进程的迁移,即在不中断其他正在运行的应用程序的情况下,将应用程序从一个节点迁移到另一个节点。
迁移流程:
1. 在源节点上为目标进程创建一个检查点镜像(checkpoint image)。
2. 将该镜像传输到目标节点。
3. 在目标节点上使用该镜像恢复进程。
重要限制:新节点必须拥有与原始节点相同类型的GPU。
触发检查点的方式:
- 管理员通过命令行启动的透明检查点:
$ cuda-checkpoint -action lock -pid 1234
- 通过CUDA API以编程方式启动的检查点:
cuCheckpointProcess(1234, CU_CHECKPOINT_LOCK);
更多信息可参考博客文章:Checkpointing CUDA Applications with CRIU。
9. 附录
9.1. GTC 2025 CUDA 开发者会议
以下是推荐的GTC 2025 CUDA开发者相关会议列表:
- 通用CUDA (General CUDA)
- S72571 - What's CUDA All About Anyways? (CUDA到底是什么?)
- S72897 - How To Write A CUDA Program: The Parallel Programming Edition (如何编写CUDA程序:并行编程版) - CUDA Python
- S72570 - Accelerated Python: The Community and Ecosystem (加速Python:社区与生态系统)
- S72448 - The CUDA Python Developer's Toolbox (CUDA Python开发者工具箱)
- S72449 - 1001 Ways to Write CUDA Kernels in Python (用Python编写CUDA核函数的1001种方法)
- S74639 - Enable Tensor Core Programming in Python With CUTLASS 4.0 (使用CUTLASS 4.0在Python中启用Tensor Core编程) - CUDA C++
- S72574 - Building CUDA Software at the Speed-of-Light (以光速构建CUDA软件)
- S72572 - The CUDA C++ Developer's Toolbox (CUDA C++开发者工具箱)
- S72575 - How You Should Write a CUDA C++ Kernel (你应该如何编写CUDA C++核函数) - 开发者工具 (Developer Tools)
- S72527 - It's Easier than You Think - Debugging and Optimizing CUDA with Intelligent Developer Tools (比你想象的更简单 - 使用智能开发者工具调试和优化CUDA) - 与专家交流 (Connect with the Experts)
- CWE72433 - CUDA Developer Best Practices (CUDA开发者最佳实践)
- CWE73310 - Using NVIDIA CUDA Compiler Tool Chain for Productive GPGPU Programming (使用NVIDIA CUDA编译器工具链进行高效的GPGPU编程)
- CWE72393 - What's in Your Developer Toolbox? CUDA and Graphics Profiling, Optimization, and Debugging Tools (你的开发者工具箱里有什么?CUDA与图形分析、优化和调试工具) - 多GPU编程 (Multi-GPU Programming)
- S72576 - Getting Started with Multi-GPU Scaling: Distributed Libraries (多GPU扩展入门:分布式库)
- S72579 - Going Deeper with Multi-GPU Scaling: Task-based Runtimes (深入多GPU扩展:基于任务的运行时)
- S72578 - Advanced Multi-GPU Scaling: Communication Libraries (高级多GPU扩展:通信库) - 性能优化 (Performance Optimization)
- S72683 - CUDA Techniques to Maximize Memory Bandwidth and Hide Latency (最大化内存带宽和隐藏延迟的CUDA技术)
- S72685 - CUDA Techniques to Maximize Compute and Instruction Throughput (最大化计算和指令吞吐量的CUDA技术)
- S72686 - CUDA Techniques to Maximize Concurrency and System Utilization (最大化并发和系统利用率的CUDA技术)
- S72687 - Get the Most Performance from Grace Hopper (从Grace Hopper获取最佳性能)
更多会议信息请访问:nvidia.com/gtc/sessions/cuda-developer
9.2. 参考演讲
以下是本报告中引用的相关演讲和博客文章列表:
- S72571 What's CUDA All About Anyways? (CUDA到底是什么?)
- S72867 AI Developer Tools for Accelerated Computing - Scarce Data Isn't Scary (用于加速计算的AI开发者工具 - 稀疏数据并不可怕)
- S72448 The CUDA Python Developer's Toolbox (CUDA Python开发者工具箱)
- S72450 Accelerated Python: The Community and Ecosystem (加速Python:社区与生态系统)
- S72449 1001 Ways to Write CUDA Kernels in Python (用Python编写CUDA核函数的1001种方法)
- S72527 It's Easier than You Think - Debugging and Optimizing CUDA with Intelligent Developer Tools (比你想象的更简单 - 使用智能开发者工具调试和优化CUDA)
- S72434 How Math Libraries Can Help Accelerate Your Applications on Blackwell GPUs (数学库如何帮助你在Blackwell GPU上加速应用)
- S71350 A Deep Dive Into the Latest HPC Software (深入了解最新的HPC软件)
- S72897 How To Write A CUDA Program: The Parallel Programming Edition (如何编写CUDA程序:并行编程版)
- S72572 The CUDA C++ Developer's Toolbox (CUDA C++开发者工具箱)
- S72876 Blackwell Programming for the Masses with OpenAI Triton (使用OpenAI Triton为大众进行Blackwell编程)
- S72720 Programming Blackwell Tensor Cores with CUTLASS (使用CUTLASS进行Blackwell Tensor Core编程)
- S74639 Enable Tensor Core Programming in Python With CUTLASS 4.0 (使用CUTLASS 4.0在Python中启用Tensor Core编程)
- CWE73310 Using NVIDIA CUDA Compiler Tool Chain for Productive GPGPU Programming (使用NVIDIA CUDA编译器工具链进行高效的GPGPU编程)
- CWE74695 Seamlessly Scale Python Programs From Single-CPU to Multi-GPU, Multi-Node Clusters With cuPyNumeric (使用cuPyNumeric将Python程序从单CPU无缝扩展到多GPU、多节点集群)
- CWE72456 Performance Analysis and Optimization (性能分析与优化)
- CWE72433 CUDA Developer Best Practices (CUDA开发者最佳实践)
- Exhibits B062 (Warp for CAE) | B043 (Warp for Robotics) | B049 (ALCHEMI using Warp for material science) (展览)
- Blog Introducing Tile-Based Programming in Warp 1.5.0 (博客:在Warp 1.5.0中引入基于Tile的编程)
- Blog Checkpointing CUDA Applications with CRIU (博客:使用CRIU对CUDA应用程序进行检查点操作)