在使用nvcc构建时,我仍然不确定如何正确指定代码生成的体系结构。我知道我的二进制文件中嵌入了机器代码和PTX代码,这可以通过控制器开关-code
和-arch
(或使用-gencode
两者的组合来控制)。
现在,根据this除了两个编译器标志之外,还有两种指定体系结构的方法:sm_XX
和compute_XX
,其中compute_XX
指的是虚拟和sm_XX
到真正的架构。标志-arch
仅获取虚拟体系结构的标识符(例如compute_XX
),而-code
标记获取真实体系结构和虚拟体系结构的标识符。
文档指出-arch
指定了为其编译输入文件的虚拟体系结构。但是,此PTX代码不会自动编译为机器代码,但这是一个"预处理步骤"。
现在,-code
应该指定PTX代码的汇编和优化架构。
但是,不清楚哪个PTX或二进制代码将嵌入二进制文件中。如果我指定例如-arch=compute_30 -code=sm_52
,这是否意味着我的代码将首先被编译为功能级别3.0 PTX,之后将创建功能级别5.2的机器代码?什么将被嵌入?
如果我只指定-code=sm_52
会发生什么呢?只嵌入V5.2的机器代码是用V5.2 PTX代码创建的?那对-code=compute_52
会有什么不同?
答案 0 :(得分:25)
在使用nvcc构建时,我仍然不确定如何正确指定代码生成的体系结构。
完整的描述有点复杂,但有一些相对简单,易于记忆的规范用法。编译体系结构(虚拟和真实),代表您希望定位的GPU。一个相当简单的形式是:
-gencode arch=compute_XX,code=sm_XX
其中XX是您希望定位的GPU的两位数计算能力。如果您希望定位多个GPU,只需重复每个XX目标的整个序列。这大致是CUDA示例代码项目采用的方法。 (如果您希望在可执行文件中包含PTX,请添加-gencode
并code
选项指定与arch
选项相同的PTX虚拟架构。
另一个相当简单的形式,仅针对单个GPU时,只需使用:
-arch=sm_XX
与XX的描述相同。此表单将包括指定体系结构的SASS和PTX。
现在,除了两个编译器标志之外,还有两种指定体系结构的方法:sm_XX和compute_XX,其中compute_XX表示虚拟,sm_XX表示真实体系结构。 flag -arch只接受虚拟体系结构的标识符(例如compute_XX),而-code标记接受真实体系结构和虚拟体系结构的标识符。
当arch
和code
用作-gencode
交换机中的子交换机,或者两者一起使用时,这基本上是正确的,独立的你形容。但是,例如,当-arch
单独使用(没有-code
)时,它代表另一种"简写"符号,在这种情况下,您可以传递真实的架构,例如-arch=sm_52
但是,不清楚哪个PTX或二进制代码将嵌入二进制文件中。如果我指定例如-arch = compute_30 -code = sm_52,那是否意味着我的代码将首先编译为功能级别3.0 PTX,然后从中创建功能级别5.2的机器代码?什么将被嵌入?
嵌入内容的确切定义因使用形式而异。但是对于这个例子:
-gencode arch=compute_30,code=sm_52
或您确定的同等情况:
-arch=compute_30 -code=sm_52
然后是的,这意味着:
ptxas
工具将生成符合cc5.2标准的SASS代码。(我不确定为什么你会真正指定这样的组合,但它是合法的。)
如果我只是指定-code = sm_52会发生什么呢?只嵌入V5.2的机器代码是用V5.2 PTX代码创建的?什么是-code = compute_52?
的区别
-code=sm_52
将从中间PTX代码生成cc5.2 SASS代码。将嵌入SASS代码,PTX将被丢弃。请注意,在此表单中单独指定此选项(不带-arch
选项)将是非法的。 (1)
-code=compute_52
将生成cc5.x PTX代码(仅)并将该PTX嵌入可执行文件/二进制文件中。请注意,在此表单中单独指定此选项(不带-arch
选项)将是非法的。 (1)
cuobjdump
tool可用于识别给定二进制文件中的确切组件。
(1)如果没有使用-gencode
开关,并且没有使用-arch
开关,nvcc
假定您的编译命令附加了默认-arch=sm_20
(这是对于CUDA 7.5,默认-arch
设置可能因CUDA版本而异。 sm_20
是一个真正的架构,当-arch
选项在-code
选项上指定真实架构是不合法的也提供。