什么是 GPU 编程?
在高性能计算领域,GPU(图形处理器)无处不在,而特定领域的科研人员正面临着日益严峻的挑战:他们需要调整自己的计算机程序,以充分利用这些先进的 GPU 系统。这项工作对于释放这些高科技 GPU 架构的全部潜力至关重要。
本文将为希望了解“什么是 GPU 编程?”的读者提供 GPU 编程的基础知识。此外,您还将了解不同的 GPU 编程方法和框架,以及最流行的 GPU 编程平台 CUDA(它在 Python 中同样广泛使用)及其在 GPU 编程中的重要性。
什么是 GPU?
图形处理器(GPU)是一种电子电路,它通过快速操作内存并同时处理数据,加速生成用于显示的图像。如今 GPU 已无处不在,广泛存在于个人电脑、游戏主机、专业工作站甚至智能手机等各种计算设备中。
随着时间推移,GPU 在性能上超越了 CPU,拥有更多的晶体管,并在并行计算方面表现出色。GPU 已发展成为拥有自己的内存、总线和处理器的复杂设备,可以被视为计算机系统的又一个“大脑”或处理器。
什么是 GPU 编程?
GPU 编程是指利用 GPU 加速器同时执行大量通用计算操作。过去,GPU 主要用于计算机图形处理,但如今它们也被用于各种通用计算任务。除了图形处理之外,GPU 现在还被大量用于科学建模、机器学习以及其他可以通过同时处理多项任务来提速的工作。
GPU 与 CPU 有什么区别?
GPU 计算与 CPU 计算的主要区别在于二者的架构差异。由于高度并行的特性,在处理可以拆分并以多种方式处理的数据时,GPU 比 CPU 更高效。GPU 专门针对矩阵运算和浮点运算等密集型计算进行了优化。
CPU 与 GPU 处理能力存在差异的原因在于,GPU 被设计用于执行高度并行、计算密集的任务,而这正是图形渲染所需要的。
在 GPU 的架构中,数据处理的优先级高于数据缓存和流程控制。以并行方式解决问题时有两个显著的好处:第一,每个元素都执行相同的运算,从而减少了对复杂流程控制的需求;第二,数据集规模大、算术强度高,降低了对低延迟内存的需求。
有哪些不同的 GPU 编程方法或 API?
使用 GPU 进行计算可以采用不同的方法。在最简单的情况下,如果代码已经写好,调整参数和初始配置可能就足够了。另一种方式是使用库来处理代码中计算最密集的部分。不过,对于更复杂的场景,可能需要进行一定的编程。
目前有多种 GPU 编程软件环境和 API 可供选择,可分为基于指令的模型、不可移植的基于内核的模型、可移植的基于内核的模型,以及高级框架和库。
标准 C++/Fortran
使用标准 C++ 和 Fortran 语言编写的程序无需外部库即可利用 NVIDIA GPU。NVIDIA SDK 编译器会针对 GPU 执行对代码进行优化,具体可参考相关指南。
基于指令的编程
基于指令的方法是在现有的串行代码中添加注解,标明需要在 GPU 上执行的循环和代码区域。以 OpenACC 和 OpenMP 为代表的这种方法注重开发效率和易用性,但可能会牺牲一些性能。
OpenACC:OpenACC 是一个成立于 2010 年的联盟,旨在为包括 GPU 在内的加速器提供标准、可移植且可扩展的编程模型。它最初仅支持 NVIDIA GPU,但正在扩展对更多设备和架构的支持。
OpenMP:OpenMP 最初是面向多核 CPU 的共享内存并行编程 API,现在已支持 GPU 卸载,可面向多种类型的 GPU。
不可移植的基于内核的模型(原生编程模型)
直接 GPU 编程通过直接与 GPU 通信的底层代码,为开发者提供更大的控制权。典型例子包括 CUDA(NVIDIA)和 HIP(AMD),其中 HIP 旨在实现 NVIDIA 与 AMD GPU 之间的交叉兼容。
可移植的基于内核的模型(跨平台可移植生态)
Alpaka、Kokkos、OpenCL、RAJA 和 SYCL 等跨平台可移植生态提供了更高层次的抽象,让 GPU 编程更加便捷且可移植。它们的目标是通过单一源代码的应用程序实现性能可移植性。
Kokkos:由桑迪亚国家实验室开发,Kokkos 是一个基于 C++ 的生态系统,支持在 CPU、GPU 和 FPGA 上构建高效、可扩展的并行应用程序。
OpenCL:OpenCL 是一种用于在各类硬件上进行通用并行计算的开放标准 API,为 GPU 编程提供底层编程接口。它支持多家厂商的 CPU、GPU 和 FPGA。
SYCL:SYCL 是一种免版税、开放标准的 C++ 编程模型,为包括 GPU 在内的异构系统提供高级的单一源代码编程模型。它可以构建在 OpenCL、CUDA 或 HIP 之上。
高级语言支持
Python 通过多个库支持 GPU 编程,每个库都有其独特用途:
CuPy
- 基于 GPU 的数据数组库。
- 与 NumPy/SciPy 无缝集成。
- 只需在 Python 代码中将 'numpy' 和 'scipy' 替换为 'cupy' 和 'cupyx.scipy',即可轻松过渡到 GPU 计算。
cuDF(RAPIDS)
- RAPIDS 的一部分,通过 Python 绑定实现 CUDA 功能。
- 专为在 GPU 上操作数据框(DataFrame)而设计。
- 提供类似 pandas 的 API,让熟悉 Pandas 的用户无需深入了解 CUDA 即可加速工作。
PyCUDA
- 面向 CUDA 的 Python 编程环境。
- 可从 Python 访问 NVIDIA 的 CUDA API。
- 仅限 NVIDIA GPU,且需要具备 CUDA 编程经验。
Numba
- 支持对 Python 代码进行即时(JIT)编译,以便在 GPU 上执行。
- 支持 NVIDIA GPU,并计划在未来加入对 AMD GPU 的支持。
这些库为 Python 中的 GPU 编程提供了多样化的选择,可满足不同用户的偏好和需求。无论是通过 CuPy 从 NumPy/SciPy 过渡,还是使用 cuDF 类似 pandas 的 API,Python 都能为高效的 GPU 加速计算提供灵活性。
什么是 CUDA?
CUDA 是由 NVIDIA 打造的并行计算平台和 API,开创了主流 GPU 编程框架的时代。这项技术使开发者能够编写在 GPU 上运行的类 C++ 代码。
CUDA 不仅提供了丰富的库和工具用于探索底层 GPU 编程,还能显著提升计算密集型应用程序的效率。需要注意的是,尽管拥有如此强大的生态系统,CUDA 仍仅限于 NVIDIA 硬件。
如何在 Ubuntu 20.04 上安装 CUDA 以进行 GPU 编程
您可以按照以下分步说明在 Ubuntu 20.04 上安装 CUDA:
步骤 1:首先,使用 ‘wget’ 或 ‘curl’ 命令下载在 Ubuntu 20.04 上配置 CUDA 软件源所需的 CUDA Pin 配置文件(cuda-ubuntu2004.pin)。
$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
步骤 2:将下载的 pin 配置文件移动到指定目录,并将其 pin 优先级设置为 600。
$ sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
步骤 3:下载 CUDA 软件源安装包:
wget https://developer.download.nvidia.com/compute/cuda/11.4.2/local_installers/cuda-repo-ubuntu2004-11-4-local_11.4.2-470.57.02-1_amd64.deb
步骤 4:使用 dpkg 包管理器安装下载的 CUDA 软件源安装包。
$ sudo dpkg -i cuda-repo-ubuntu2004-11-4-local_11.4.2-470.57.02-1_amd64.deb
步骤 5:添加用于验证 CUDA 软件源的公钥。
$ sudo apt-key add /var/cuda-repo-ubuntu2004-11-4-local/7fa2af80.pub
步骤 6:更新软件包列表:
$ sudo apt-get update
使用新添加的 CUDA 软件源中的信息更新本地软件包列表。
步骤 7:现在,使用以下命令在您的 Ubuntu 20.04 机器上安装 CUDA 工具包:
$ sudo apt-get -y install cuda
按照上述步骤,您就可以在配备支持 CUDA 的 GPU 并运行 Ubuntu 20.04 的机器上安装 CUDA。现在,您可以在 Linux 机器上运行 GPU 代码并使用 CUDA 平台了。
总结
选择 GPU 编程环境取决于目标硬件平台、计算性质和开发者经验等因素。与特定 GPU 的兼容性、与项目需求的契合度,以及开发者对高级简洁性或底层控制的偏好,都是做出最佳选择时需要重点考虑的因素。