From 8617c28221cac2bd89402178b25dcd47445a9349 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 15 Sep 2023 11:47:28 -0400 Subject: CUDA: Factor out helper for detecting native CUDA architectures Prepare to use it for other languages. --- Modules/CMakeCUDACompilerABI.cu | 25 +---------- Modules/CMakeCompilerCUDAArch.h | 29 +++++++++++++ Modules/CMakeTestCUDACompiler.cmake | 49 ++-------------------- .../Internal/CMakeCUDAArchitecturesNative.cmake | 49 ++++++++++++++++++++++ 4 files changed, 84 insertions(+), 68 deletions(-) create mode 100644 Modules/CMakeCompilerCUDAArch.h create mode 100644 Modules/Internal/CMakeCUDAArchitecturesNative.cmake diff --git a/Modules/CMakeCUDACompilerABI.cu b/Modules/CMakeCUDACompilerABI.cu index 8463e86..b04d0ec 100644 --- a/Modules/CMakeCUDACompilerABI.cu +++ b/Modules/CMakeCUDACompilerABI.cu @@ -2,11 +2,8 @@ # error "A C or C++ compiler has been selected for CUDA" #endif -#include - -#include - #include "CMakeCompilerABI.h" +#include "CMakeCompilerCUDAArch.h" int main(int argc, char* argv[]) { @@ -19,25 +16,7 @@ int main(int argc, char* argv[]) #endif static_cast(argv); - int count = 0; - if (cudaGetDeviceCount(&count) != cudaSuccess || count == 0) { - std::fprintf(stderr, "No CUDA devices found.\n"); - return -1; - } - - int found = 0; - const char* sep = ""; - for (int device = 0; device < count; ++device) { - cudaDeviceProp prop; - if (cudaGetDeviceProperties(&prop, device) == cudaSuccess) { - std::printf("%s%d%d", sep, prop.major, prop.minor); - sep = ";"; - found = 1; - } - } - - if (!found) { - std::fprintf(stderr, "No CUDA architecture detected from any devices.\n"); + if (!cmakeCompilerCUDAArch()) { // Convince the compiler that the non-zero return value depends // on the info strings so they are not optimized out. return require ? -1 : 1; diff --git a/Modules/CMakeCompilerCUDAArch.h b/Modules/CMakeCompilerCUDAArch.h new file mode 100644 index 0000000..dcb030f --- /dev/null +++ b/Modules/CMakeCompilerCUDAArch.h @@ -0,0 +1,29 @@ +#include + +#include + +static bool cmakeCompilerCUDAArch() +{ + int count = 0; + if (cudaGetDeviceCount(&count) != cudaSuccess || count == 0) { + std::fprintf(stderr, "No CUDA devices found.\n"); + return -1; + } + + bool found = false; + const char* sep = ""; + for (int device = 0; device < count; ++device) { + cudaDeviceProp prop; + if (cudaGetDeviceProperties(&prop, device) == cudaSuccess) { + std::printf("%s%d%d", sep, prop.major, prop.minor); + sep = ";"; + found = true; + } + } + + if (!found) { + std::fprintf(stderr, "No CUDA architecture detected from any devices.\n"); + } + + return found; +} diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake index 79ee20f..3057fe9 100644 --- a/Modules/CMakeTestCUDACompiler.cmake +++ b/Modules/CMakeTestCUDACompiler.cmake @@ -22,51 +22,10 @@ if(CMAKE_CUDA_ABI_COMPILED) set(CMAKE_CUDA_COMPILER_WORKS TRUE) message(STATUS "Check for working CUDA compiler: ${CMAKE_CUDA_COMPILER} - skipped") - # Run the test binary to detect the native architectures. - execute_process(COMMAND "${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerABI_CUDA.bin" - RESULT_VARIABLE _CUDA_ARCHS_RESULT - OUTPUT_VARIABLE _CUDA_ARCHS_OUTPUT - ERROR_VARIABLE _CUDA_ARCHS_OUTPUT - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - if(_CUDA_ARCHS_RESULT EQUAL 0) - if("$ENV{CMAKE_CUDA_ARCHITECTURES_NATIVE_CLAMP}") - # Undocumented hook used by CMake's CI. - # Clamp native architecture to version range supported by this CUDA. - list(GET CMAKE_CUDA_ARCHITECTURES_ALL 0 _CUDA_ARCH_MIN) - list(GET CMAKE_CUDA_ARCHITECTURES_ALL -1 _CUDA_ARCH_MAX) - set(CMAKE_CUDA_ARCHITECTURES_NATIVE "") - foreach(_CUDA_ARCH IN LISTS _CUDA_ARCHS_OUTPUT) - if(_CUDA_ARCH LESS _CUDA_ARCH_MIN) - set(_CUDA_ARCH "${_CUDA_ARCH_MIN}") - endif() - if(_CUDA_ARCH GREATER _CUDA_ARCH_MAX) - set(_CUDA_ARCH "${_CUDA_ARCH_MAX}") - endif() - list(APPEND CMAKE_CUDA_ARCHITECTURES_NATIVE ${_CUDA_ARCH}) - endforeach() - unset(_CUDA_ARCH) - unset(_CUDA_ARCH_MIN) - unset(_CUDA_ARCH_MAX) - else() - set(CMAKE_CUDA_ARCHITECTURES_NATIVE "${_CUDA_ARCHS_OUTPUT}") - endif() - list(REMOVE_DUPLICATES CMAKE_CUDA_ARCHITECTURES_NATIVE) - list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_NATIVE APPEND "-real") - else() - if(NOT _CUDA_ARCHS_RESULT MATCHES "[0-9]+") - set(_CUDA_ARCHS_STATUS " (${_CUDA_ARCHS_RESULT})") - else() - set(_CUDA_ARCHS_STATUS "") - endif() - string(REPLACE "\n" "\n " _CUDA_ARCHS_OUTPUT " ${_CUDA_ARCHS_OUTPUT}") - message(CONFIGURE_LOG - "Detecting the CUDA native architecture(s) failed with " - "the following output:\n${_CUDA_ARCHS_OUTPUT}\n\n") - endif() - unset(_CUDA_ARCHS_EXE) - unset(_CUDA_ARCHS_RESULT) - unset(_CUDA_ARCHS_OUTPUT) + include(Internal/CMakeCUDAArchitecturesNative) + # Run the test binary to get: + # - CMAKE_CUDA_ARCHITECTURES_NATIVE + cmake_cuda_architectures_native(CUDA) endif() # This file is used by EnableLanguage in cmGlobalGenerator to diff --git a/Modules/Internal/CMakeCUDAArchitecturesNative.cmake b/Modules/Internal/CMakeCUDAArchitecturesNative.cmake new file mode 100644 index 0000000..4185eda --- /dev/null +++ b/Modules/Internal/CMakeCUDAArchitecturesNative.cmake @@ -0,0 +1,49 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +function(cmake_cuda_architectures_native lang) + # Run the test binary to detect the native architectures. + execute_process(COMMAND "${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerABI_${lang}.bin" + RESULT_VARIABLE archs_result + OUTPUT_VARIABLE archs_output + ERROR_VARIABLE archs_output + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(archs_result EQUAL 0) + if("$ENV{CMAKE_CUDA_ARCHITECTURES_NATIVE_CLAMP}") + # Undocumented hook used by CMake's CI. + # Clamp native architecture to version range supported by this CUDA. + list(GET CMAKE_${lang}_ARCHITECTURES_ALL 0 arch_min) + list(GET CMAKE_${lang}_ARCHITECTURES_ALL -1 arch_max) + set(CMAKE_CUDA_ARCHITECTURES_NATIVE "") + foreach(arch IN LISTS archs_output) + if(arch LESS arch_min) + set(arch "${arch_min}") + endif() + if(arch GREATER arch_max) + set(arch "${arch_max}") + endif() + list(APPEND CMAKE_CUDA_ARCHITECTURES_NATIVE ${arch}) + endforeach() + unset(arch) + unset(arch_min) + unset(arch_max) + else() + set(CMAKE_CUDA_ARCHITECTURES_NATIVE "${archs_output}") + endif() + list(REMOVE_DUPLICATES CMAKE_CUDA_ARCHITECTURES_NATIVE) + list(TRANSFORM CMAKE_CUDA_ARCHITECTURES_NATIVE APPEND "-real") + else() + if(NOT archs_result MATCHES "[0-9]+") + set(archs_status " (${archs_result})") + else() + set(archs_status "") + endif() + string(REPLACE "\n" "\n " archs_output " ${archs_output}") + message(CONFIGURE_LOG + "Detecting the CUDA native architecture(s) failed with " + "the following output${archs_status}:\n${archs_output}\n\n") + endif() + + set(CMAKE_${lang}_ARCHITECTURES_NATIVE "${CMAKE_CUDA_ARCHITECTURES_NATIVE}" PARENT_SCOPE) +endfunction() -- cgit v0.12