CMake actually offers such autodetection capability, but:
- It's undocumented (and will probably be refactored at some point in the future).
- It's part of the deprecated FindCUDA mechanism, and is geared towards direct manipulation of
CUDA_CMAKE_FLAGS
(which isnt what we want).
- 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:
When there are no GPUs on your system you may get a result such as: 3.5;5.0;5.3;6.0;6.1;7.0;7.5;7.5+PTX
.
This is an issue with CMake which will not be resolved, since the submodule we're using here is not officially supported. So, if you need to compile on systems with no GPUs, either avoid this call or parse your results for the "+PTX" entry.
The select_compute_arch
submodule has existed for much longer, but in the past you would use it differently, and would include it through include(FindCUDA)
.
I wonder if LIST(APPEND CMAKE_CUDA_ARCHITECTURES
might not be more appropriate than SET(CMAKE_CUDA_ARCHITECTURES
.
See CMake issues 22375 and 19199 for where CMake might go with this in the future. Caveat: I filed those bugs...