Как я могу заставить CMake автоматически определять значение CUDA_ARCHITECTURES?

Более новые версии CMake (3.18 и новее) "осведомлены" о выборе архитектур CUDA, на которые нацелена компиляция кода CUDA. Цели имеют свойство, которое, если установлено, генерирует соответствующий -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 или глобальный CMAKD_CUDA_ARCHITECTURES? То есть использовать архитектуры графических процессоров, установленных в системе?

4 ответа

В грядущем CMake 3.24 вы сможете писать:

      set_property(TARGET tgt PROPERTY CUDA_ARCHITECTURES native)

и это создаст цель tgtдля (конкретных) архитектур CUDA графических процессоров, доступных в вашей системе во время настройки.

В более новых версиях CUDA (11.5 и выше) nativeна nvcc и другие исполняемые файлы; в более старых версиях он автоматически определяет, какие архитектуры являются «родными».

CMake на самом деле предлагает такую ​​возможность автоопределения, но:

  1. Это недокументировано (и, вероятно, в какой-то момент в будущем будет произведен рефакторинг).
  2. Это часть устаревшего механизма FindCUDA и предназначена для прямого управления CUDA_CMAKE_FLAGS (что не то, что мы хотим).
  3. Он не "играет хорошо" и скрывает от нас свои внутренние переменные полезной формы.

Тем не менее, немного смазки для локтей, мы можем заставить его работать.

Во-первых, это местоположение: это в модуле, FindCUDA/elect_compute_arch (который в системе Linux будет расположен в /path/to/cmake/root/share/cmake-X.YY/Modules/FindCUDA/elect_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 "." "" INSTALLED_GPU_CC_LIST "${INSTALLED_GPU_CCS_3}")
LIST(APPEND CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH_LIST})

Если вам нужно это только для одной цели, вы должны заменить последнюю строку на:

      set_property(TARGET my_target PROPERTY ${CUDA_ARCH_LIST})

Обратите внимание select_compute_arch модуль существует гораздо дольше, но раньше вы использовали его по-другому и включали бы его через include(FindCUDA).

У меня были проблемы с использованием другого решения с системой с 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 ..
Другие вопросы по тегам