我最近了解了NVCC如何为不同的计算架构编译CUDA设备代码。
根据我的理解,当使用NVCC的-gencode选项时,“arch”是程序员应用程序所需的最小计算体系结构,也是NVCC的JIT编译器为其编译PTX代码的最小设备计算体系结构。
我也明白-gencode的“code”参数是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 / code对?上面是否使用了“arch”的所有值?
它之间的区别是什么:
-arch compute_20
-code sm_20
-code sm_21
“arch”字段中最早的虚拟架构是自动选择还是存在其他一些模糊的行为?
我应该注意其他任何编译和运行时行为吗?
我已经阅读了手册http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-compilation,我仍然不清楚编译或运行时会发生什么。
答案 0 :(得分:39)
粗略地说,代码编译流程如下:
CUDA C / C ++设备代码源 - > PTX - > SASS
虚拟架构(例如compute_20
,无论-arch compute...
指定的是什么)确定将生成什么类型的PTX代码。附加开关(例如-code sm_21
)确定将生成什么类型的SASS代码。 SASS实际上是GPU(机器语言)的可执行目标代码。可执行文件可以包含多个版本的SASS和/或PTX,并且有一个运行时加载器机制,它将根据实际使用的GPU选择适当的版本。
正如您所指出的,GPU操作的一个便利功能是JIT编译。 JIT-compile将由GPU驱动程序完成(不需要安装CUDA工具包),只要有合适的PTX代码,但不适合的SASS代码。
包含多个虚拟体系结构(即多个版本的PTX)的一个优点是,您可以与更多种类的目标GPU设备兼容(尽管某些设备可能会触发JIT编译以创建必要的SASS)
包含多个“真实GPU目标”(即多个SASS版本)的一个优点是,当存在其中一个目标设备时,您可以避免JIT编译步骤。
如果指定了一组错误的选项,则可以创建一个无法在特定GPU上正常运行的可执行文件。
指定大量这些选项的一个可能的缺点是代码大小膨胀。另一个可能的缺点是编译时间,当您指定更多选项时,编译时间通常会更长。
也可以创建不包含PTX的excutable,这可能是那些试图掩盖其IP的人感兴趣的。
创建适合JIT的PTX应由specifying a virtual architecture code
开关。
答案 1 :(得分:2)
多个-arch
标志的目的是使用__CUDA_ARCH__
宏进行条件编译(即使用#ifdef
)不同优化的代码路径。