1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
|
set(Kokkos_DEVICES @KOKKOS_ENABLED_DEVICES@)
set(Kokkos_OPTIONS @KOKKOS_ENABLED_OPTIONS@)
set(Kokkos_TPLS @KOKKOS_ENABLED_TPLS@)
set(Kokkos_ARCH @KOKKOS_ENABLED_ARCH_LIST@)
set(Kokkos_CXX_COMPILER "@CMAKE_CXX_COMPILER@")
set(Kokkos_CXX_COMPILER_ID "@KOKKOS_CXX_COMPILER_ID@")
set(Kokkos_CXX_COMPILER_VERSION "@KOKKOS_CXX_COMPILER_VERSION@")
set(Kokkos_CXX_STANDARD @KOKKOS_CXX_STANDARD@)
# Required to be a TriBITS-compliant external package
if(NOT TARGET Kokkos::all_libs)
add_library(Kokkos::all_libs ALIAS Kokkos::kokkos)
endif()
# Export Kokkos_ENABLE_<BACKEND> for each backend that was enabled.
# NOTE: "Devices" is a little bit of a misnomer here. These are really
# backends, e.g. Kokkos_ENABLE_OPENMP, Kokkos_ENABLE_CUDA, Kokkos_ENABLE_HIP,
# or Kokkos_ENABLE_SYCL.
foreach(DEV ${Kokkos_DEVICES})
set(Kokkos_ENABLE_${DEV} ON)
endforeach()
# Export relevant Kokkos_ENABLE<OPTION> variables, e.g.
# Kokkos_ENABLE_CUDA_RELOCATABLE_DEVICE_CODE, Kokkos_ENABLE_DEBUG, etc.
foreach(OPT ${Kokkos_OPTIONS})
set(Kokkos_ENABLE_${OPT} ON)
endforeach()
if(Kokkos_ENABLE_CUDA)
set(Kokkos_CUDA_ARCHITECTURES @KOKKOS_CUDA_ARCHITECTURES@)
endif()
if(Kokkos_ENABLE_HIP)
set(Kokkos_HIP_ARCHITECTURES @KOKKOS_HIP_ARCHITECTURES@)
endif()
if(NOT Kokkos_FIND_QUIETLY)
message(STATUS "Enabled Kokkos devices: ${Kokkos_DEVICES}")
endif()
if(Kokkos_ENABLE_CUDA)
# If we are building CUDA, we have tricked CMake because we declare a CXX project
# If the default C++ standard for a given compiler matches the requested
# standard, then CMake just omits the -std flag in later versions of CMake
# This breaks CUDA compilation (CUDA compiler can have a different default
# -std then the underlying host compiler by itself). Setting this variable
# forces CMake to always add the -std flag even if it thinks it doesn't need it
set(CMAKE_CXX_STANDARD_DEFAULT 98 CACHE INTERNAL "" FORCE)
endif()
set(KOKKOS_USE_CXX_EXTENSIONS @KOKKOS_USE_CXX_EXTENSIONS@)
if(NOT DEFINED CMAKE_CXX_EXTENSIONS OR CMAKE_CXX_EXTENSIONS)
if(NOT KOKKOS_USE_CXX_EXTENSIONS)
message(
WARNING "The installed Kokkos configuration does not support CXX extensions. Forcing -DCMAKE_CXX_EXTENSIONS=Off"
)
set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "" FORCE)
endif()
endif()
# This function makes sure that Kokkos was built with the requested backends
# and target architectures and generates a fatal error if it was not.
#
# kokkos_check(
# [DEVICES <devices>...] # Set of backends (e.g. "OpenMP" and/or "Cuda")
# [ARCH <archs>...] # Target architectures (e.g. "Power9" and/or "Volta70")
# [OPTIONS <options>...] # Optional settings (e.g. "TUNING")
# [TPLS <tpls>...] # Third party libraries
# [RETURN_VALUE <result>] # Set a variable that indicates the result of the
# # check instead of a fatal error
# )
function(kokkos_check)
set(ALLOWED_ARGS DEVICES ARCH OPTIONS TPLS)
cmake_parse_arguments(KOKKOS_CHECK "" "RETURN_VALUE" "${ALLOWED_ARGS}" ${ARGN})
foreach(_arg ${KOKKOS_CHECK_UNPARSED_ARGUMENTS})
message(SEND_ERROR "Argument '${_arg}' passed to kokkos_check() was not recognized")
endforeach()
# Get the list of keywords that were actually passed to the function.
set(REQUESTED_ARGS)
foreach(arg ${ALLOWED_ARGS})
if(KOKKOS_CHECK_${arg})
list(APPEND REQUESTED_ARGS ${arg})
endif()
endforeach()
set(KOKKOS_CHECK_SUCCESS TRUE)
foreach(arg ${REQUESTED_ARGS})
set(MISSING_OPTIONS "")
foreach(requested ${KOKKOS_CHECK_${arg}})
set(FOUND_MATCHING_OPTION FALSE)
foreach(provided ${Kokkos_${arg}})
string(TOUPPER ${requested} REQUESTED_UC)
string(TOUPPER ${provided} PROVIDED_UC)
if(PROVIDED_UC STREQUAL REQUESTED_UC)
set(FOUND_MATCHING_OPTION TRUE)
endif()
endforeach()
if(NOT FOUND_MATCHING_OPTION)
list(APPEND MISSING_OPTIONS ${requested})
set(KOKKOS_CHECK_SUCCESS FALSE)
endif()
endforeach()
if(NOT KOKKOS_CHECK_SUCCESS AND NOT KOKKOS_CHECK_RETURN_VALUE)
message(STATUS "Could NOT find Kokkos_${arg} (missing: ${MISSING_OPTIONS})")
endif()
endforeach()
if(NOT KOKKOS_CHECK_SUCCESS AND NOT KOKKOS_CHECK_RETURN_VALUE)
message(FATAL_ERROR "Kokkos does NOT provide all backends and/or architectures requested")
else()
set(${KOKKOS_CHECK_RETURN_VALUE} ${KOKKOS_CHECK_SUCCESS} PARENT_SCOPE)
endif()
endfunction()
# A test to check whether a downstream project set the C++ compiler to NVCC or not
# this is called only when Kokkos was installed with Kokkos_ENABLE_CUDA=ON
function(kokkos_compiler_is_nvcc VAR COMPILER)
# Check if the compiler is nvcc (which really means nvcc_wrapper).
execute_process(
COMMAND ${COMPILER} ${ARGN} --version
OUTPUT_VARIABLE INTERNAL_COMPILER_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE RET
)
# something went wrong
if(RET GREATER 0)
set(${VAR} false PARENT_SCOPE)
else()
string(REPLACE "\n" " - " INTERNAL_COMPILER_VERSION_ONE_LINE ${INTERNAL_COMPILER_VERSION})
string(FIND ${INTERNAL_COMPILER_VERSION_ONE_LINE} "nvcc" INTERNAL_COMPILER_VERSION_CONTAINS_NVCC)
string(REGEX REPLACE "^ +" "" INTERNAL_HAVE_COMPILER_NVCC "${INTERNAL_HAVE_COMPILER_NVCC}")
if(${INTERNAL_COMPILER_VERSION_CONTAINS_NVCC} GREATER -1)
set(${VAR} true PARENT_SCOPE)
else()
set(${VAR} false PARENT_SCOPE)
endif()
endif()
endfunction()
# this function checks whether the current CXX compiler supports building CUDA
function(kokkos_cxx_compiler_cuda_test _VAR _COMPILER)
file(
WRITE ${PROJECT_BINARY_DIR}/compile_tests/compiles_cuda.cu
"
#include <cuda.h>
#include <cstdlib>
__global__
void kernel(int sz, double* data)
{
int _beg = blockIdx.x * blockDim.x + threadIdx.x;
for(int i = _beg; i < sz; ++i)
data[i] += static_cast<double>(i);
}
int main()
{
double* data = NULL;
int blocks = 64;
int grids = 64;
int ret = cudaMalloc(&data, blocks * grids * sizeof(double));
if(ret != cudaSuccess)
return EXIT_FAILURE;
kernel<<<grids, blocks>>>(blocks * grids, data);
cudaDeviceSynchronize();
return EXIT_SUCCESS;
}
"
)
# save the command for debugging
set(_COMMANDS "${_COMPILER} ${ARGN} -c ${PROJECT_BINARY_DIR}/compile_tests/compiles_cuda.cu")
# use execute_process instead of try compile because we want to set custom compiler
execute_process(
COMMAND ${_COMPILER} ${ARGN} -c ${PROJECT_BINARY_DIR}/compile_tests/compiles_cuda.cu
RESULT_VARIABLE _RET
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/compile_tests
TIMEOUT 15
OUTPUT_QUIET ERROR_QUIET
)
if(NOT _RET EQUAL 0)
# save the command for debugging
set(_COMMANDS
"${_COMMAND}\n${_COMPILER} --cuda-gpu-arch=sm_50 ${ARGN} -c ${PROJECT_BINARY_DIR}/compile_tests/compiles_cuda.cu"
)
# try the compile test again with clang arguments
execute_process(
COMMAND ${_COMPILER} --cuda-gpu-arch=sm_50 -c ${PROJECT_BINARY_DIR}/compile_tests/compiles_cuda.cu
RESULT_VARIABLE _RET
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/compile_tests
TIMEOUT 15
OUTPUT_QUIET ERROR_QUIET
)
endif()
set(${_VAR}_COMMANDS "${_COMMANDS}" PARENT_SCOPE)
set(${_VAR} ${_RET} PARENT_SCOPE)
endfunction()
# this function is provided to easily select which files use the same compiler as Kokkos
# when it was installed (or nvcc_wrapper):
#
# GLOBAL --> all files
# TARGET --> all files in a target
# SOURCE --> specific source files
# DIRECTORY --> all files in directory
# PROJECT --> all files/targets in a project/subproject
#
# Use the COMPILER argument to specify a compiler, if needed. By default, it will
# set the values to ${Kokkos_CXX_COMPILER} unless Kokkos_ENABLE_CUDA=ON and
# Kokkos_CXX_COMPILER_ID is NVIDIA, then it will set it to nvcc_wrapper
#
# Use CHECK_CUDA_COMPILES to run a check when CUDA is enabled
#
function(kokkos_compilation)
cmake_parse_arguments(
COMP "GLOBAL;PROJECT;CHECK_CUDA_COMPILES" "COMPILER" "DIRECTORY;TARGET;SOURCE;COMMAND_PREFIX" ${ARGN}
)
# if built w/o CUDA support, we want to basically make this a no-op
set(_Kokkos_ENABLE_CUDA @Kokkos_ENABLE_CUDA@)
# search relative first and then absolute
set(_HINTS "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../.." "@CMAKE_INSTALL_PREFIX@")
# find kokkos_launch_compiler
find_program(
Kokkos_COMPILE_LAUNCHER
NAMES kokkos_launch_compiler
HINTS ${_HINTS}
PATHS ${_HINTS}
PATH_SUFFIXES bin
)
if(NOT Kokkos_COMPILE_LAUNCHER)
message(
FATAL_ERROR
"Kokkos could not find 'kokkos_launch_compiler'. Please set '-DKokkos_COMPILE_LAUNCHER=/path/to/launcher'"
)
endif()
# if COMPILER was not specified, assume Kokkos_CXX_COMPILER
if(NOT COMP_COMPILER)
set(COMP_COMPILER ${Kokkos_CXX_COMPILER})
if(_Kokkos_ENABLE_CUDA AND Kokkos_CXX_COMPILER_ID STREQUAL NVIDIA)
# find nvcc_wrapper
find_program(
Kokkos_NVCC_WRAPPER
NAMES nvcc_wrapper
HINTS ${_HINTS}
PATHS ${_HINTS}
PATH_SUFFIXES bin
)
# fatal if we can't nvcc_wrapper
if(NOT Kokkos_NVCC_WRAPPER)
message(
FATAL_ERROR "Kokkos could not find nvcc_wrapper. Please set '-DKokkos_NVCC_WRAPPER=/path/to/nvcc_wrapper'"
)
endif()
set(COMP_COMPILER ${Kokkos_NVCC_WRAPPER})
endif()
endif()
# check that the original compiler still exists!
if(NOT EXISTS ${COMP_COMPILER})
message(FATAL_ERROR "Kokkos could not find original compiler: '${COMP_COMPILER}'")
endif()
# try to ensure that compiling cuda code works!
if(_Kokkos_ENABLE_CUDA AND COMP_CHECK_CUDA_COMPILES)
# this may fail if kokkos_compiler launcher was used during install
kokkos_cxx_compiler_cuda_test(_COMPILES_CUDA ${Kokkos_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER})
# if above failed, throw an error
if(NOT _COMPILES_CUDA)
message(FATAL_ERROR "kokkos_cxx_compiler_cuda_test failed! Test commands:\n${_COMPILES_CUDA_COMMANDS}")
endif()
endif()
if(COMP_COMMAND_PREFIX)
set(_PREFIX "${COMP_COMMAND_PREFIX}")
string(REPLACE ";" " " _PREFIX "${COMP_COMMAND_PREFIX}")
set(Kokkos_COMPILER_LAUNCHER "${_PREFIX} ${Kokkos_COMPILE_LAUNCHER}")
endif()
if(COMP_GLOBAL)
# if global, don't bother setting others
set_property(
GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${Kokkos_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}"
)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${Kokkos_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}")
else()
foreach(_TYPE PROJECT DIRECTORY TARGET SOURCE)
# make project/subproject scoping easy, e.g. KokkosCompilation(PROJECT) after project(...)
if("${_TYPE}" STREQUAL "PROJECT" AND COMP_${_TYPE})
list(APPEND COMP_DIRECTORY ${PROJECT_SOURCE_DIR})
unset(COMP_${_TYPE})
endif()
# set the properties if defined
if(COMP_${_TYPE})
# MESSAGE(STATUS "Using ${COMP_COMPILER} :: ${_TYPE} :: ${COMP_${_TYPE}}")
set_property(
${_TYPE} ${COMP_${_TYPE}} PROPERTY RULE_LAUNCH_COMPILE
"${Kokkos_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}"
)
set_property(
${_TYPE} ${COMP_${_TYPE}} PROPERTY RULE_LAUNCH_LINK
"${Kokkos_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}"
)
endif()
endforeach()
endif()
endfunction()
|