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实际上提供了这样的自动检测功能,但是:
- 它是未记录的(可能会在未来的某个时候进行重构(
- 它是已弃用的FindCUDA机制的一部分,旨在直接操作
CUDA_CMAKE_FLAGS
(这不是我们想要的( - 它不是";玩得好";,并向我们隐藏其有用的内部变量形式
不过,只要稍微涂一点润滑脂,我们就能让它发挥作用。
首先,它的位置:它在一个模块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 ..