CUDA: Factor out helper for detecting native CUDA architectures

Prepare to use it for other languages.
This commit is contained in:
Brad King
2023-09-15 11:47:28 -04:00
parent 0db0fe7958
commit 8617c28221
4 changed files with 84 additions and 68 deletions

View File

@@ -2,11 +2,8 @@
# error "A C or C++ compiler has been selected for CUDA"
#endif
#include <cstdio>
#include <cuda_runtime.h>
#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<void>(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;

View File

@@ -0,0 +1,29 @@
#include <cstdio>
#include <cuda_runtime.h>
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;
}

View File

@@ -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

View File

@@ -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()