42

我最近了解了 NVCC 如何为不同的计算架构编译 CUDA 设备代码。

据我了解,当使用 NVCC 的 -gencode 选项时,“arch”是程序员的应用程序所需的最小计算架构,也是 NVCC 的 JIT 编译器将为其编译 PTX 代码的最小设备计算架构。

我也明白 -gencode 的“代码”参数是 NVCC 完全编译应用程序的计算架构,因此不需要 JIT 编译。

在检查了各种 CUDA 项目 Makefile 之后,我注意到以下情况经常发生:

-gencode arch=compute_20,code=sm_20
-gencode arch=compute_20,code=sm_21
-gencode arch=compute_21,code=sm_21

经过一番阅读,我发现可以在一个二进制文件中编译多个设备架构 - 在本例中为 sm_20、sm_21。

我的问题是为什么需要这么多拱门/代码对?上面是否使用了“arch”的所有值?

那和说有什么区别:

-arch compute_20
-code sm_20
-code sm_21

“arch”字段中最早的虚拟架构是自动选择的,还是有其他一些晦涩的行为?

还有其他我应该注意的编译和运行时行为吗?

我已经阅读了手册http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-compilation,但我仍然不清楚编译或运行时会发生什么。

4

2 回答 2

52

粗略地说,代码编译流程是这样的:

CUDA C/C++ 设备代码源 --> PTX --> SASS

虚拟架构(例如compute_20,由 指定的任何内容-arch compute...)确定将生成哪种类型的 PTX 代码。附加开关(例如-code sm_21)确定将生成哪种类型的 SASS 代码。SASS 实际上是 GPU(机器语言)的可执行目标代码。一个可执行文件可以包含多个版本的 SASS 和/或 PTX,并且有一个运行时加载器机制可以根据实际使用的 GPU 选择适当的版本。

正如您所指出的,GPU 操作的便利功能之一是 JIT 编译。只要有合适的 PTX 代码可用,但没有合适的 SASS 代码,GPU 驱动程序将完成 JIT 编译(不需要安装 CUDA 工具包)。“合适的 PTX”代码的定义是在数值上等于或低于运行代码的目标 GPU 架构。举个例子,指定arch=compute_30,code=compute_30将告诉 nvcc 在可执行文件中嵌入 cc3.0 PTX 代码。此 PTX 代码可用于为 GPU 驱动程序支持的任何未来架构生成 SASS 代码。目前这将包括 Pascal、Volta、Turing 等架构,假设 GPU 驱动程序支持这些架构。

那么,包含多个虚拟架构(即 PTX 的多个版本)的一个优点是,您可以与更广泛的目标 GPU 设备具有可执行兼容性(尽管某些设备可能会触发 JIT 编译以创建必要的 SASS)。

包含多个“真正的 GPU 目标”(即多个 SASS 版本)的一个优点是,当其中一个目标设备存在时,您可以避免 JIT 编译步骤。

如果您指定了一组错误的选项,则可能会创建一个无法在特定 GPU 上(正确)运行的可执行文件。

指定大量这些选项的一个可能缺点是代码大小膨胀。另一个可能的缺点是编译时间,当您指定更多选项时,编译时间通常会更长。

还可以创建不包含 PTX 的可执行文件,这对于那些试图掩盖其 IP 的人可能会感兴趣。

创建适合 JIT 的 PTX 应该通过为交换机指定虚拟架构来完成。code

于 2013-07-11T17:18:27.677 回答
4

多个-arch标志的目的是使用__CUDA_ARCH__宏进行不同优化代码路径的条件编译(即使用#ifdef)。

见这里:http ://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#virtual-architecture-identification-macro

于 2017-07-15T05:14:46.790 回答