【问题标题】:How can I get CMake to automatically detect the value for CUDA_ARCHITECTURES?如何让 CMake 自动检测 CUDA_ARCHITECTURES 的值?
【发布时间】:2021-09-14 07:15:38
【问题描述】:

较新版本的 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 cuda nvidia build-automation compute-capability


    【解决方案1】:

    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

      这是一个issue with CMake which will not be resolved,因为我们在这里使用的子模块不受官方支持。因此,如果您需要在没有 GPU 的系统上进行编译,请避免此调用或解析“+PTX”条目的结果。

    • select_compute_arch 子模块已经存在了很长时间,但在过去你会以不同的方式使用它,并通过include(FindCUDA) 包含它。

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

    • 请参阅 CMake 问题 2237519199,了解 CMake 未来可能会采用的方式。警告:我提交了这些错误...

    【讨论】:

    • set_property(TARGET my_target PROPERTY "${CUDA_ARCH_LIST}")(带引号)可能会更好一些,因为如果变量为空,则会产生硬语法错误。
    • 这在使用 CMake 3.13 的系统中对我不起作用,我不得不对该系统使用 `cuda_select_nvcc_arch_flags(ARCH_FLAGS "Auto")`,这不适用于更高版本的 CMake (例如 3.16)。请参阅我的其他答案。
    【解决方案2】:

    我在使用带有 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 2020-01-01
      相关资源
      最近更新 更多