cmakecudanvidiabuild-automationcompute-capability

How can I get CMake to automatically detect the value for CUDA_ARCHITECTURES?


Newer versions of CMake (3.18 and later), are "aware" of the choice of CUDA architectures which compilation of CUDA code targets. Targets have a CUDA_ARCHITECTURES property, which, when set, generates the appropriate -gencode arch=whatever,code=whatever compilation options for you. You will even get a warning if you don't set this value:

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

by default, this target property is initialized to CMAKE_CUDA_ARCHITECTURES. But CMAKE_CUDA_ARCHITECTURES itself is not initialized to anything (!)

How can we have CMake auto-detect an appropriate value for CUDA_ARCHITECTURES or the global CMAKD_CUDA_ARCHITECTURES? That is, use the architectures of GPUs installed on the system?


Solution

  • CMake actually offers such autodetection capability, but:

    1. It's undocumented (and will probably be refactored at some point in the future).
    2. It's part of the deprecated FindCUDA mechanism, and is geared towards direct manipulation of CUDA_CMAKE_FLAGS (which isnt what we want).
    3. It doesn't "play nice", and hides its useful-form internal variables from us.

    Still, with a little elbow grease, we can make it work.

    First, its location: It's in a module, FindCUDA/select_compute_arch (which, on a Linux system, will be located in /path/to/cmake/root/share/cmake-X.YY/Modules/FindCUDA/select_compute_arch.cmake).

    Now here's how you use it:

    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})
    

    If you only want this for a single target, you would replace the last line with:

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

    Notes: