From df8f583cd461facaa3ae058d45dbeb2e7d7c91c9 Mon Sep 17 00:00:00 2001 From: Peter Heywood Date: Tue, 28 Nov 2023 19:26:18 +0000 Subject: [PATCH] Switch to CCCL 2.2.0+ from Thrust/Cub 1.x Closes #1021 --- cmake/common.cmake | 2 +- cmake/dependencies/CCCL.cmake | 71 +++++++++++++++++ cmake/dependencies/Thrust.cmake | 130 -------------------------------- src/CMakeLists.txt | 5 +- 4 files changed, 74 insertions(+), 134 deletions(-) create mode 100644 cmake/dependencies/CCCL.cmake delete mode 100644 cmake/dependencies/Thrust.cmake diff --git a/cmake/common.cmake b/cmake/common.cmake index 408ac0a0d..10cf3ed2a 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -28,7 +28,7 @@ endif() # Ensure that other dependencies are downloaded and available. # As flamegpu is a static library, linking only only occurs at consumption not generation, so dependent targets must also know of PRIVATE shared library dependencies such as tinyxml2 and rapidjson, as well any intentionally public dependencies (for include dirs) -include(${CMAKE_CURRENT_LIST_DIR}/dependencies/Thrust.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/dependencies/CCCL.cmake) include(${CMAKE_CURRENT_LIST_DIR}/dependencies/Jitify.cmake) include(${CMAKE_CURRENT_LIST_DIR}/dependencies/Tinyxml2.cmake) include(${CMAKE_CURRENT_LIST_DIR}/dependencies/rapidjson.cmake) diff --git a/cmake/dependencies/CCCL.cmake b/cmake/dependencies/CCCL.cmake new file mode 100644 index 000000000..848c38e97 --- /dev/null +++ b/cmake/dependencies/CCCL.cmake @@ -0,0 +1,71 @@ +################################### +# CCCL (Thrust, CUB and libcucxx) # +################################### + +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/modules/ ${CMAKE_MODULE_PATH}) + +include(FetchContent) +cmake_policy(SET CMP0079 NEW) + +# Set the minimum supported CCCL version, and the version to fetch +# using find_package(version) means it's up to CCCL's cmake to determine if newer versions are compatible, but this will likely need changing for CUDA 13, when CCCL is planned to have a major version bump (and drop CUDA 11 support). +set(MIN_REQUIRED_CCCL_VERSION 2.2.0) +set(CCCL_DOWNLOAD_TAG v2.2.0) + +# Use the FindCUDATooklit package (CMake > 3.17) to get the CUDA version and CUDA include directories for cub/thrust location hints +find_package(CUDAToolkit REQUIRED) + +# Quietly find CCCL, to check if the version included with CUDA (if CCCL) is sufficiently new. +# Using CCCL avoids complex cub/thrust version workarounds previously required. +# However we cannot find thrust due to a missing guard in CCCL's cmake config file, and cannot find cub without finding libcudacxx, so just find libcudacxx quietly. +# If/when we change the minimum CCCL to 2.3.0 we should be able to remove the `components libcudacxx`. +find_package(CCCL ${MIN_REQUIRED_CCCL_VERSION} QUIET COMPONENTS libcudacxx CONFIG HINTS ${CUDAToolkit_INCLUDE_DIRS} ${CUDAToolkit_LIBRARY_DIR}/cmake) + +# If CCCL was found, find it again but loudly (with all components) +if(CCCL_FOUND) + # Find the packages again but less quietly (and include all components) + find_package(CCCL ${MIN_REQUIRED_CCCL_VERSION} REQUIRED CONFIG COMPONENTS HINTS ${CUDAToolkit_INCLUDE_DIRS} ${CUDAToolkit_LIBRARY_DIR}/cmake) +# If CCCL does need downloading, fetch it and find it (no need to add_subdirectory) +else() + # Declare information about where and what we want from thrust. + FetchContent_Declare( + cccl + GIT_REPOSITORY https://github.com/NVIDIA/CCCL.git + GIT_TAG ${CCCL_DOWNLOAD_TAG} + GIT_SHALLOW 1 + GIT_PROGRESS ON + # UPDATE_DISCONNECTED ON + ) + # Fetch and populate the content if required. + FetchContent_GetProperties(cccl) + if(NOT cccl_POPULATED) + message(STATUS "Fetching CCCL ${CCCL_DOWNLOAD_TAG}") + FetchContent_Populate(cccl) + # Use find_package for CCLL, only looking for the fetched version. + # This creates a non-system target due to nvcc magic to avoid the cuda toolkit version being used instead, so warnings are not suppressible without push/pop macros. + find_package(CCCL REQUIRED CONFIG + PATHS "${cccl_SOURCE_DIR}" + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_PACKAGE_REGISTRY + NO_CMAKE_SYSTEM_PATH) + endif() + # Mark some CACHE vars as advanced for a cleaner CMake GUI + mark_as_advanced(FETCHCONTENT_QUIET) + mark_as_advanced(FETCHCONTENT_BASE_DIR) + mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) + mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) + mark_as_advanced(FETCHCONTENT_SOURCE_DIR_CCCL) + mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_CCCL) +endif() + +# Unset temporary variables +unset(MIN_REQUIRED_CCCL_VERSION) +unset(CCCL_DOWNLOAD_TAG) + +# Mark some CACHE vars as advanced for a cleaner CMake GUI +mark_as_advanced(CCCL_DIR) +mark_as_advanced(CUB_DIR) +mark_as_advanced(Thrust_DIR) +mark_as_advanced(libcudacxx_DIR) diff --git a/cmake/dependencies/Thrust.cmake b/cmake/dependencies/Thrust.cmake deleted file mode 100644 index 3f8bc8690..000000000 --- a/cmake/dependencies/Thrust.cmake +++ /dev/null @@ -1,130 +0,0 @@ -#################### -# Thrust (and CUB) # -#################### - -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/modules/ ${CMAKE_MODULE_PATH}) - -include(FetchContent) -cmake_policy(SET CMP0079 NEW) - -# Set the minimum supported cub/thrust version, and the version to fetch -# Thrust minimum version to 1.16 to avoid windows.h related issues and pull in bug fixes, but fetch the most recent 1.x release otherwise (at the time of writing). -set(MIN_REQUIRED_THRUST_VERSION 1.16.0) -set(MIN_REQUIRED_CUB_VERSION ${MIN_REQUIRED_THRUST_VERSION}) -set(THRUST_DOWNLOAD_VERSION 1.17.2) - -# Use the FindCUDATooklit package (CMake > 3.17) to get the CUDA version and CUDA include directories for cub/thrust location hints -find_package(CUDAToolkit REQUIRED) - -# Quietly find Thrust and CUB, to check if an appropriate version can be found without downloading. -# thrust-config.cmake and cub-config.cmake live in different locations with CUDA (on ubuntu) depending on the CUDA version. -# CUDA 11.3 and 11.4 they can be found in the CUDA Toolkit include directories. -# CUDA 11.5+ they can be found in lib/cmake or lib64/cmake -# CUDA 11.6 - 11.8 ships with CUB 1.15.0 which has a bug when windows.h is included prior to CUB, so don't try to find the regular Thrust/CUB in this case. -# Ideally we would detect 1.15.0 and then download the correct version of CUB/Thrust, but getting CMake on windows to behave was proving problematic -if(NOT (MSVC AND CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.6.0 AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11.9.0)) - find_package(Thrust QUIET CONFIG HINTS ${CUDAToolkit_INCLUDE_DIRS} ${CUDAToolkit_LIBRARY_DIR}/cmake) - find_package(CUB QUIET CONFIG HINTS ${CUDAToolkit_INCLUDE_DIRS} ${CUDAToolkit_LIBRARY_DIR}/cmake) -endif() - -# By default, assume we have to fetch thrust/cub -set(FETCH_THRUST_CUB 1) -# If a useful version was found, find it again less quietly -if(Thrust_FOUND AND Thrust_VERSION VERSION_GREATER_EQUAL MIN_REQUIRED_THRUST_VERSION AND CUB_FOUND AND CUB_VERSION VERSION_GREATER_EQUAL MIN_REQUIRED_CUB_VERSION) - set(FETCH_THRUST_CUB 0) - # Find the packages again but less quietly. - find_package(Thrust CONFIG REQUIRED HINTS ${CUDAToolkit_INCLUDE_DIRS} ${CUDAToolkit_LIBRARY_DIR}/cmake) - find_package(CUB CONFIG REQUIRED HINTS ${CUDAToolkit_INCLUDE_DIRS} ${CUDAToolkit_LIBRARY_DIR}/cmake) -# Otherwise unfind Thrust/CUB. -else() - # Unset a number of thrust / cub cache variables so that re-finding behaves as intended. - unset(THRUST_DIR) - unset(THRUST_DIR CACHE) - unset(THRUST_DEVICE_SYSTEM_OPTIONS) - unset(THRUST_DEVICE_SYSTEM_OPTIONS CACHE) - unset(THRUST_HOST_SYSTEM_OPTIONS) - unset(THRUST_HOST_SYSTEM_OPTIONS CACHE) - unset(THRUST_VERSION) - unset(THRUST_VERSION CACHE) - unset(THRUST_VERSION_COUNT) - unset(THRUST_VERSION_COUNT CACHE) - unset(THRUST_VERSION_MAJOR) - unset(THRUST_VERSION_MAJOR CACHE) - unset(THRUST_VERSION_MINOR) - unset(THRUST_VERSION_MINOR CACHE) - unset(THRUST_VERSION_PATCH) - unset(THRUST_VERSION_PATCH CACHE) - unset(THRUST_VERSION_TWEAK) - unset(THRUST_VERSION_TWEAK CACHE) - unset(_THRUST_CMAKE_DIR) - unset(_THRUST_CMAKE_DIR CACHE) - unset(_THRUST_INCLUDE_DIR) - unset(_THRUST_INCLUDE_DIR CACHE) # This is the most important one for Thrust 2.0, which just THRUST_DIR was insufficient for. - unset(_THRUST_QUIET) - unset(_THRUST_QUIET CACHE) - unset(_THRUST_QUIET_FLAG) - unset(_THRUST_QUIET_FLAG CACHE) - unset(CUB_DIR) - unset(CUB_DIR CACHE) - unset(_CUB_INCLUDE_DIR) - unset(_CUB_INCLUDE_DIR CACHE) -endif() - -# If thrust/cub do need downloading, fetch them, and find them. -# As they are header only, they can just be found rather than add_subdirectoried. -if(FETCH_THRUST_CUB) - # Declare information about where and what we want from thrust. - FetchContent_Declare( - thrust - GIT_REPOSITORY https://github.com/NVIDIA/thrust.git - GIT_TAG ${THRUST_DOWNLOAD_VERSION} - GIT_SHALLOW 1 - GIT_PROGRESS ON - # UPDATE_DISCONNECTED ON - ) - - # Fetch and populate the content if required. - FetchContent_GetProperties(thrust) - if(NOT thrust_POPULATED) - message(STATUS "Fetching Thrust ${THRUST_DOWNLOAD_VERSION}") - FetchContent_Populate(thrust) - # Use find_package for thrust, only looking for the fetched version. - # This creates a non-system target due to nvcc magic to avoid the cuda toolkit version being used instead, so warnings are not suppressable. - find_package(Thrust REQUIRED CONFIG - PATHS ${thrust_SOURCE_DIR} - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_PACKAGE_REGISTRY - NO_CMAKE_SYSTEM_PATH) - # Use find_package for cub, only looking for the fetched version. - # This creates a non-system target due to nvcc magic to avoid the cuda toolkit version being used instead, so warnings are not suppressable. - # Look in the symlinked and non-symlinked locations, preferring non symlinked due to windows (and the symlink being removed from 2.0) - find_package(CUB REQUIRED CONFIG - PATHS - ${thrust_SOURCE_DIR}/dependencies/cub/cub/cmake/ - ${thrust_SOURCE_DIR}/cub/cmake - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_PACKAGE_REGISTRY - NO_CMAKE_SYSTEM_PATH) - endif() - # Mark some CACHE vars as advnaced for a cleaner CMake GUI - mark_as_advanced(FETCHCONTENT_QUIET) - mark_as_advanced(FETCHCONTENT_BASE_DIR) - mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) - mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) - mark_as_advanced(FETCHCONTENT_SOURCE_DIR_THRUST) - mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_THRUST) -endif() - -# Unset temporary variables -unset(FETCH_THRUST_CUB) -unset(MIN_REQUIRED_THRUST_VERSION) -unset(MIN_REQUIRED_CUB_VERSION) -unset(THRUST_DOWNLOAD_VERSION) - -# Mark some CACHE vars as advnaced for a cleaner CMake GUI -mark_as_advanced(CUB_DIR) -mark_as_advanced(Thrust_DIR) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 258b6e947..12ca80e48 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -584,9 +584,8 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY CUDA_SEPARABLE_COMPILATION ON) # Link against dependency targets / directories. -# Cub and thrust targets are not imported targets, so they do not use -isystem, so warnings must be suppressed as pragmas as requied. This is due to nvcc magic preventing isystem from being reliable with them. -target_link_libraries(${PROJECT_NAME} PUBLIC CUB::CUB) -target_link_libraries(${PROJECT_NAME} PUBLIC Thrust::Thrust) +# CCCL for Cub and thrust (and libcudacxx) targets are not imported targets, so they do not use -isystem, so warnings must be suppressed as pragmas if required. This is due to nvcc magic implicit include directory search ordering +target_link_libraries(${PROJECT_NAME} PUBLIC CCCL::CCCL) # tinyxml2 static library target_link_libraries(${PROJECT_NAME} PRIVATE Tinyxml2::tinyxml2)