我对 '-gencode' 语句中的 'code=sm_X' 选项有点困惑。
示例:NVCC 编译器选项有什么作用
-gencode arch=compute_13,code=sm_13
Run Code Online (Sandbox Code Playgroud)
嵌入库中?
只有与CC 1.3,或GPU的机器代码(代码的cubin)也与CC 1.3的GPU的PTX代码?
在“Maxwell 兼容性指南”中,声明“只有由 'code=' 子句指定的后端目标版本将保留在生成的二进制文件中”。
由此,我推断给定的编译器选项仅嵌入了带有 CC 1.3 且没有PTX 代码的GPU 的机器代码。这意味着,这将不能够运行这个库例如,AA麦克斯韦代卡上,因为是从机器代码可能是“刚刚在时间”(JIT)编译库中没有内嵌代码PTX。
另一方面,在 NVIDIA 的 GTC 2013 演示文稿“作为应用程序构建工具的 CUDA 工具包简介”中,它表示“-gencode arch=compute_13,code=sm_13”对于所有 CC >= 1.3 的 GPU 来说就足够了,并且对于 CC > 1.3 的 GPU 使用此编译器选项,机器代码是从 PTX 代码进行 JIT 化的。因此,在我看来,Maxwell 兼容性指南和 GTC 演示中给出的信息是相互矛盾的。
nvcc
有许多格式可以指定代码生成选项。阅读nvcc 手册的第 6 节可能会有所启发。
使用此格式时:
nvcc -gencode arch=compute_13,code=sm_13 ...
Run Code Online (Sandbox Code Playgroud)
只保留 sm_13 (cc 1.3) 设备的 SASS 代码。可执行对象中不会保留 PTX,因此代码只能在能够运行 cc1.3 SASS 的设备上运行。
使用上述命令格式,为了将源代码的 PTX 版本嵌入到可执行对象中,需要使用虚拟架构规范提供给code=...
. 由于这种特定格式(使用-gencode
)不允许在单个开关中指定多个目标,因此我们必须-gencode
多次将开关传递给 nvcc,每个目标都对应一个我们希望嵌入到可执行对象中的目标。
所以扩展上面的例子,我们可以使用以下内容:
nvcc -gencode arch=compute_13,code=sm_13 -gencode arch=compute_13,code=compute_13 ...
Run Code Online (Sandbox Code Playgroud)
这将在可执行文件中嵌入 cc1.3 SASS(通过第一个gencode
开关)和 cc1.3 PTX(通过第二个gencode
开关)。能够直接运行 cc1.3 SASS 代码的设备将使用它。其他设备(计算能力大于 cc 1.3)将由驱动程序执行 JIT 编译步骤,以将 cc1.3 PTX 代码转换为具有适合相关设备的架构的 SASS 代码。
我同意GTC 2013 演示文稿(例如幻灯片 37)似乎表明
nvcc -gencode arch=compute_13,code=sm_13 ...
Run Code Online (Sandbox Code Playgroud)
足以满足所有计算能力为 1.3 或更高的设备。事实并非如此,这很容易证明。如果您使用上述格式编译代码,并尝试在 cc 2.0 设备上运行它,它将失败并显示与您的代码中的任何内核相关联的“无效设备功能”错误。
同样,nvcc
具有用于指定代码生成的各种命令格式和“快捷方式”。一些比较简单的,比如:
nvcc -arch=sm_13 ...
Run Code Online (Sandbox Code Playgroud)
将在可执行对象中嵌入代码的 PTX 和 SASS 版本,从而产生建议的向前兼容性。