Как я могу заставить 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 на самом деле предлагает такую возможность автоопределения, но:
- Это недокументировано (и, вероятно, в какой-то момент в будущем будет произведен рефакторинг).
- Это часть устаревшего механизма FindCUDA и предназначена для прямого управления
CUDA_CMAKE_FLAGS
(что не то, что мы хотим). - Он не "играет хорошо" и скрывает от нас свои внутренние переменные полезной формы.
Тем не менее, немного смазки для локтей, мы можем заставить его работать.
Во-первых, это местоположение: это в модуле,
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 ..