如何让CMake自动检测CUDA_ARCHITECTURES的值



CMake的较新版本(3.18及更高版本(是;意识到";CUDA代码的编译所针对的CUDA架构的选择。目标具有CUDA_ARCHITECTURES属性,该属性在设置时会为您生成适当的-gencode arch=whatever,code=whatever编译选项。如果你不设置这个值,你甚至会收到警告:

CMake Error in CMakeLists.txt:
CUDA_ARCHITECTURES is empty for target "my_cuda_app".

默认情况下,此目标属性初始化为CMAKE_CUDA_ARCHITECTURES。但是CMAKE_CUDA_ARCHITECTURES本身并没有初始化为任何(!(

我们如何让CMake自动检测CUDA_ARCHITECTURES或全局CMAKD_CUDA_ARCHITECTURES的适当值?也就是说,使用安装在系统上的GPU的体系结构?

在即将推出的CMake 3.24中,您将能够编写:

set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES native)

这将为您的系统在配置时可用的GPU的(具体的(CUDA架构构建目标CCD_ 7。

对于较新版本的CUDA(11.5及更高版本(,将把native传递给nvcc和其他可执行文件;对于旧版本,它将自动检测哪些架构是"本机"架构。

注意事项:这实际上并没有给你架构列表(例如,在你的CMake代码中迭代。(

CMake实际上提供了这样的自动检测功能,但是:

  1. 它是未记录的(可能会在未来的某个时候进行重构(
  2. 它是已弃用的FindCUDA机制的一部分,旨在直接操作CUDA_CMAKE_FLAGS(这不是我们想要的(
  3. 它不是";玩得好";,并向我们隐藏其有用的内部变量形式

不过,只要稍微涂一点润滑脂,我们就能让它发挥作用。

首先,它的位置:它在一个模块FindCUDA/select_compute_arch中(在Linux系统上,它将位于/path/to/cmake/root/share/cmake-X.YY/Modules/FindCUDA/select_compute_arch.cmake中(。

下面是如何使用它:

include(FindCUDA/select_compute_arch)
CUDA_DETECT_INSTALLED_GPUS(INSTALLED_GPU_CCS_1)
string(STRIP "${INSTALLED_GPU_CCS_1}" INSTALLED_GPU_CCS_2)
string(REPLACE " " ";" INSTALLED_GPU_CCS_3 "${INSTALLED_GPU_CCS_2}")
string(REPLACE "." "" CUDA_ARCH_LIST "${INSTALLED_GPU_CCS_3}")
SET(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH_LIST})

如果你只想把它用于一个目标,你可以把最后一行替换为:

set_property(TARGET my_target PROPERTY "${CUDA_ARCH_LIST}")

注:

  • 当您的系统上没有GPU时,您可能会得到这样的结果:3.5;5.0;5.3;6.0;6.1;7.0;7.5;7.5+PTX

    这是CMake的一个问题,不会得到解决,因为我们在这里使用的子模块没有得到官方支持。因此,如果你需要在没有GPU的系统上编译,要么避免这个调用,要么解析你的"+PTX";进入

  • select_compute_arch子模块存在的时间要长得多,但在过去,您会以不同的方式使用它,并通过include(FindCUDA)将其包括在内。

  • 我想知道LIST(APPEND CMAKE_CUDA_ARCHITECTURES是否比SET(CMAKE_CUDA_ARCHITECTURES更合适。

  • 请参阅CMake第22375期和第19199期,了解CMake在未来的发展方向。卡维特:我把那些虫子归档了。。。

我在使用CMake 3.13系统的另一个解决方案时遇到了问题,不确定它是什么,但我不得不使用它。

也许有更好的方法可以做到这一点。

if(${CMAKE_VERSION} VERSION_LESS_EQUAL "3.13.4")
cuda_select_nvcc_arch_flags(ARCH_FLAGS "Auto") # optional argument for arch to add
message("ARCH_FLAGS = ${ARCH_FLAGS}")
string(REPLACE "-gencode;" "--generate-code=" ARCH_FLAGS "${ARCH_FLAGS}")
string(APPEND CMAKE_CUDA_FLAGS "${ARCH_FLAGS}")
else()
include(FindCUDA/select_compute_arch)
CUDA_DETECT_INSTALLED_GPUS(INSTALLED_GPU_CCS_1)
string(STRIP "${INSTALLED_GPU_CCS_1}" INSTALLED_GPU_CCS_2)
string(REPLACE " " ";" INSTALLED_GPU_CCS_3 "${INSTALLED_GPU_CCS_2}")
string(REPLACE "." "" CUDA_ARCH_LIST "${INSTALLED_GPU_CCS_3}")
SET(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH_LIST})
set_property(GLOBAL PROPERTY CUDA_ARCHITECTURES "${CUDA_ARCH_LIST}")
endif()

我通常在cmake命令行上执行此操作,例如:

$ export CUDACXX="/usr/local/cuda/bin/nvcc"
$ cmake -DCMAKE_CUDA_ARCHITECTURES=native -DCMAKE_BUILD_TYPE=Release ..

最新更新