前言
前面几篇文章,我们了解了NVCC的作用,nvcc编译的two stage, 每个stage做了什么,怎么去选择虚拟架构和真实架构,JIT编译的原理,好处和弊端以及解决方案。本文我们将了解几个实际的nvcc编译命令。
Base Notation
nvcc提供了选项--gpu-architecture和--gpu-code。
--gpu-architecture只能选择一个值,用来指定虚拟架构的名称,如下:
--gpu-architeture=compute_50
--gpu-code可以选择一系列的真实GPU架构,如下:
--gpu-code=sm_50,sm_52
nvcc命令
nvcc x.cu --gpu-architecture=compute_50 --gpu-code=sm_50,sm_52
Shorthand
nvcc提供了一些缩写来简化命令。
Shorthand1
--gpu-code 参数可以是虚拟架构。在这种情况下,这种虚拟架构将省略第 2 阶段转换,而是嵌入第 1 阶段 PTX 结果 (即x.ptx文件)。在应用程序启动时,如果驱动程序没有找到更好的替代方案,驱动程序将使用 PTX 作为输入调用第 2 阶段编译。
nvcc x.cu --gpu-architecture=compute_50 --gpu-code=compute_50,sm_50,sm_52
Shorthand2
--gpu-code可以被省略。只有在这种情况下,--gpu-architecture可以接收真实架构的值。--gpu-code 值默认为由 --gpu-architecture 指定的 GPU 实现的最接近的虚拟架构,加上 --gpu-architecture 值本身。
如
nvcc x.cu --gpu-architecture=sm_52
等效于
nvcc x.cu --gpu-architecture=compute_52 --gpu-code=sm_52,compute_52
最接近的虚拟架构被用作 --gpu-architecture值。 如果 --gpu-architecture 值是虚拟架构,它也用作有效的 --gpu-code 值。又如
nvcc x.cu --gpu-architecture=compute_50
等效于
nvcc x.cu --gpu-architecture=compute_50 --gpu-code=compute_50
Shorthand3
--gpu-architecture 和--gpu-code都可被省略。
nvcc x.cu
等效于
nvcc x.cu --gpu-architecture=compute_52 --gpu-code=sm_52,compute_52
Extended Notation
选项 --gpu-architecture 和 --gpu-code 可用于使用通用虚拟架构(common virtual architecture)为一个或多个 GPU 生成代码的所有情况。这将导致 nvcc 阶段 1(即虚拟 PTX 汇编代码的预处理和生成)的单个调用,然后是编译阶段 2(二进制代码生成,即x.cubin),编译阶段2会为每个特定GPU重复编译.
使用一个通用虚拟架构,意味着,对于整个 nvcc 编译,所有假定的 GPU 功能都是固定的。
比如说,以下 nvcc 命令假定 sm_50 代码和 sm_53 代码均不支持半精度浮点运算:
nvcc x.cu --gpu-architecture=compute_50 --gpu-code=compute_50,sm_50,sm_53
有时需要为划分到不同的架构时执行不同的 GPU 代码生成步骤。这个时候就需要使用--generate-code,而不是使用--gpu-architecture和--gpu-code的组合。
与--gpu-architecture不同,--generate-code可能被nvcc命令重复执行。--generate-code需要子选项arch和code. 如果使用重复架构编译,那么设备代码必须使用基于架构识别宏( architecture identification macro )__CUDA_ARCH__的值的条件编译.
比如说,以下假设不支持 sm_50 和 sm_52 代码的半精度浮点运算,但完全支持 sm_53:
nvcc x.cu \
--generate-code arch=compute_50,code=sm_50 \
--generate-code arch=compute_50,code=sm_52 \
--generate-code arch=compute_53,code=sm_53
或者,将实际的 GPU 代码生成留给 CUDA 驱动程序中的 JIT 编译器:
nvcc x.cu \
--generate-code arch=compute_50,code=compute_50 \
--generate-code arch=compute_53,code=compute_53
代码子选项可以与稍微复杂的语法结合使用:
nvcc x.cu \
--generate-code arch=compute_50,code=[sm_50,sm_52] \
--generate-code arch=compute_53,code=sm_53
Virtual Architecture Identification Macro
在为compute_xy 编译的每个nvcc 编译阶段1 期间,体系结构标识宏__CUDA_ARCH__ 被分配一个三位数的值字符串xy0(以0 结尾)。
该宏可用于 GPU 函数的实现,以确定当前正在编译的虚拟架构。主机代码(非 GPU 代码)不能依赖它。
总结
至此,我们已经了解了nvcc命令的原理和基本使用。本文剩下两个章节分别是Using Separate Compilation in CUDA和Miscellaneous NVCC Usage。这两章节涉及了更多其他NVCC应用的内容,但我打算将来真正涉及到相关使用的时候再来介绍。