如何检查库编译时使用的 CUDA 计算兼容性?

use*_*089 1 c++ cuda

我在 Ubuntu 16.04 上。假设我得到了一个随机的 libtestcuda.so 文件,无论如何我可以检查编译库的 CUDA 计算兼容性吗?

我试过了

ll libtestcuda.so
Run Code Online (Sandbox Code Playgroud)

它没有显示太多。

我想知道这一点,因为如果我编译我的代码

-gencode arch=compute_30,code=sm_30;
Run Code Online (Sandbox Code Playgroud)

它在我编写的一个小型 cuda 程序上编译并运行良好,但是当我在我的 GPU 上运行 deviceQuery 时,它实际上显示了 CUDA 计算兼容性 3.5,所以我很想知道这段代码是否会在 3.0 或 3.5 架构中执行。

如果我编译并运行它

-gencode arch=compute_20,code=sm_20;
Run Code Online (Sandbox Code Playgroud)

或者

-gencode arch=compute_50,code=sm_50;
Run Code Online (Sandbox Code Playgroud)

它按预期失败。

如果我编译并运行它

-gencode arch=compute_35,code=sm_35;
Run Code Online (Sandbox Code Playgroud)

它按预期运行良好。

Rob*_*lla 5

对于使用标志来判断nvcc要编译的体系结构的一般背景,我会建议这个问题这个问题,以及nvcc 文档

在评论中讨论后,似乎有两个问题。(尽管这些问题都在考虑库,但大多数评论也同样适用于可执行对象。)

如何发现特定库已编译用于哪些架构(PTX、SASS)?

这可以使用CUDA 二进制实用程序来发现,例如cuobjdump. 特别是,-ptx开关将列出所有包含的 PTX 对象,-sass开关将列出所有包含的 SASS 对象。例如,为“真实架构”编译的库sm_30将包含sm_30SASS 代码,这将在cuobjdump输出中很明显。例如,为“虚拟架构”编译的库compute_50将包含compute_50PTX 代码,这将在cuobjdump输出中很明显。请注意,库(或任何 CUDA fatbin 对象)可能包含多种架构的代码,包括 PTX 和 SASS,或多个 SASS 版本。

如果一个库包含多个架构,我怎么知道什么将在设备上实际执行。

在应用程序启动时,CUDA 运行时会检查应用程序的二进制对象,并且粗略地说,将使用以下启发式方法来确定将在 GPU 上运行的内容:

  1. 如果二进制对象中存在精确的 SASS 匹配,则运行时将使用它用于 GPU。这意味着,例如,如果您的对象(可执行文件或库)包含 sm_35 SASS 代码的条目,并且您在 sm_35(即计算能力 3.5)GPU 上运行,则 CUDA 运行时将选择该条目。

  2. 如果第 1 项不满足,CUDA 运行时接下来将选择一个“兼容的”SASS 条目(如果存在)。这不是很好定义/指定的 AFAIK,但通常 sm30 SASS 对象应该可用于任何 sm_3x 设备,同样适用于 sm_2x 设备上的 sm20 SASS 或任何 sm_5x 设备上的 sm50 SASS。对于其他问题(例如 sm32 SASS 是否可以直接在 sm35 设备上使用),我没有一个完整的表格来指定兼容性。可以使用问题中公开的方法测试特定情况:构建仅包含特定 SASS 类型的对象,然后查看它是否会在预期的 GPU 上运行。

  3. 如果第 1 项和第 2 项不满足,CUDA 运行时将搜索兼容的 PTX 条目。对于给定的 GPU 类型的计算能力 xy,兼容 PTX 条目定义为架构 zw 的 PTX,其中 zw 小于或等于 xy cc2.0 PTX 与 cc3.5 设备兼容,例如。cc5.0 PTX 与 cc3.5 设备不兼容。一旦找到符合此标准的最高编号 PTX 条目,GPU 驱动程序将对其进行 JIT 编译,以在运行时即时生成必要的 SASS 对象。

如果第 1、2 或 3 项都不满足,GPU 代码将在任何和所有调用 CUDA 运行时库时返回运行时错误(NO BINARY FOR GPU 或类似)。

我已经掩盖了许多与“真实”和“虚拟”架构相关的概念。这是一个复杂的主题,我建议阅读上面链接的 nvcc 文档以了解背景信息。例如,任何给定的计算能力都具有可用于实 (SASS) 和虚拟 (PTX) 的相同数值架构是不正确的。例如,对于 cc 2.0,真实 (sm_20) 和虚拟 (compute_20) 架构都存在。例如,对于cc2.1,只有真实架构(sm_21)存在,虚拟架构(compute_21)不存在,应该指定compute_20架构。例如,如果您尝试为 compute_21 进行编译,这将很明显。

人们可能还会问“考虑到所有这些”,我应该为哪些架构进行编译?

这个问题已经在许多以前的 SO 问题上得到了回答,有点见仁见智。作为一个有用的参考点,我建议遵循CUDA 示例代码项目使用的策略。