FindCUDAToolkit: Add sanitizer support

This commit is contained in:
Kyle Edwards
2026-04-28 10:13:20 -04:00
parent 2786d4e6a3
commit 35747cb5e0
8 changed files with 161 additions and 3 deletions
@@ -0,0 +1,6 @@
findcudatoolkit-sanitizer-api
-----------------------------
* The :module:`FindCUDAToolkit` module now creates a ``CUDA::sanitizer``
target for the :ref:`compute-sanitizer <FindCUDAToolkit_sanitizer>`
library.
+38 -3
View File
@@ -537,6 +537,22 @@ Target Created:
- ``CUDA::bin2c``
.. _`FindCUDAToolkit_sanitizer`:
compute-sanitizer
"""""""""""""""""
.. versionadded:: 4.4
The `NVIDIA Compute Sanitizer`_ library, which allows the tracing of CUDA
runtime and driver calls.
Target Created:
- ``CUDA::sanitizer``
.. _`NVIDIA Compute Sanitizer`: https://docs.nvidia.com/compute-sanitizer
Result Variables
^^^^^^^^^^^^^^^^
@@ -1223,7 +1239,11 @@ endif()
if(CUDAToolkit_FOUND)
function(_CUDAToolkit_find_and_add_import_lib lib_name)
cmake_parse_arguments(arg "" "" "ALT;DEPS;EXTRA_PATH_SUFFIXES;EXTRA_INCLUDE_DIRS;ONLY_SEARCH_FOR" ${ARGN})
cmake_parse_arguments(arg "" "" "ALT;DEPS;EXTRA_PATH_SUFFIXES;EXTRA_INCLUDE_DIRS;ONLY_SEARCH_FOR;LIBRARY_SEARCH_DIRS" ${ARGN})
if(NOT arg_LIBRARY_SEARCH_DIRS)
set(arg_LIBRARY_SEARCH_DIRS "${CUDAToolkit_LIBRARY_SEARCH_DIRS}")
endif()
if(arg_ONLY_SEARCH_FOR)
set(search_names ${arg_ONLY_SEARCH_FOR})
@@ -1233,7 +1253,7 @@ if(CUDAToolkit_FOUND)
find_library(CUDA_${lib_name}_LIBRARY
NAMES ${search_names}
HINTS ${CUDAToolkit_LIBRARY_SEARCH_DIRS}
HINTS ${arg_LIBRARY_SEARCH_DIRS}
ENV CUDA_PATH
PATH_SUFFIXES nvidia/current lib64 ${_CUDAToolkit_win_search_dirs} lib
# Support NVHPC splayed math library layout
@@ -1248,7 +1268,7 @@ if(CUDAToolkit_FOUND)
if(NOT CUDA_${lib_name}_LIBRARY)
find_library(CUDA_${lib_name}_LIBRARY
NAMES ${search_names}
HINTS ${CUDAToolkit_LIBRARY_SEARCH_DIRS}
HINTS ${arg_LIBRARY_SEARCH_DIRS}
ENV CUDA_PATH
PATH_SUFFIXES lib64/stubs ${_CUDAToolkit_win_stub_search_dirs} lib/stubs stubs
)
@@ -1515,6 +1535,21 @@ if(CUDAToolkit_FOUND)
add_executable(CUDA::bin2c IMPORTED)
set_property(TARGET CUDA::bin2c PROPERTY IMPORTED_LOCATION "${CUDA_bin2c_EXECUTABLE}")
endif()
_CUDAToolkit_find_and_add_import_lib(
sanitizer
ONLY_SEARCH_FOR sanitizer-public
LIBRARY_SEARCH_DIRS
"${CUDAToolkit_LIBRARY_ROOT}/compute-sanitizer"
"${CUDAToolkit_LIBRARY_ROOT}/Sanitizer"
"${CUDAToolkit_LIBRARY_ROOT}/extras/Sanitizer"
EXTRA_INCLUDE_DIRS "${CUDAToolkit_CUPTI_INCLUDE_DIR}"
)
if(TARGET CUDA::sanitizer)
get_property(loc TARGET CUDA::sanitizer PROPERTY IMPORTED_LOCATION)
get_filename_component(sanitizer_dir "${loc}" DIRECTORY)
target_include_directories(CUDA::sanitizer INTERFACE "${sanitizer_dir}/include")
endif()
endif()
if(_CUDAToolkit_Pop_ROOT_PATH)
+1
View File
@@ -32,3 +32,4 @@ endif()
add_cuda_test_macro(Cuda.WithC CudaWithC)
add_cuda_test_macro(Cuda.Bin2C CudaBin2C)
add_cuda_test_macro(Cuda.Sanitizer ${CMAKE_CTEST_COMMAND} --output-on-failure)
+20
View File
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 4.3)
project(Sanitizer CXX)
enable_testing()
# Goal for this example:
# Validate that we can use CUDAToolkit sanitizer
find_package(CUDAToolkit REQUIRED)
if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.1)
add_executable(CudaSanitizer test_sanitizer.cpp)
target_link_libraries(CudaSanitizer PRIVATE CUDA::sanitizer CUDA::cudart_static)
add_test(NAME CudaSanitizer COMMAND CudaSanitizer)
if(WIN32)
get_property(sanitizer_path TARGET CUDA::sanitizer PROPERTY IMPORTED_LOCATION)
get_filename_component(sanitizer_dir "${sanitizer_path}" DIRECTORY)
set_property(TEST CudaSanitizer PROPERTY ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:${sanitizer_dir}")
endif()
endif()
+74
View File
@@ -0,0 +1,74 @@
#include <iostream>
#include <cuda_runtime.h>
#include <sanitizer.h>
#include <stddef.h>
namespace {
bool malloc_called = false;
bool free_called = false;
void sanitizer_callback(void* userdata, Sanitizer_CallbackDomain domain,
Sanitizer_CallbackId cbid, void const* cbdata)
{
if (domain == SANITIZER_CB_DOMAIN_RESOURCE) {
switch (cbid) {
case SANITIZER_CBID_RESOURCE_DEVICE_MEMORY_ALLOC:
malloc_called = true;
break;
case SANITIZER_CBID_RESOURCE_DEVICE_MEMORY_FREE:
free_called = true;
break;
default:
break;
}
}
}
}
#define SANITIZER_TRY(call) \
do { \
SanitizerResult result; \
if ((result = (call)) != SANITIZER_SUCCESS) { \
const char* result_str; \
sanitizerGetResultString(result, &result_str); \
std::cerr << __FILE__ << ":" << __LINE__ << ": " << result_str << "\n"; \
return 1; \
} \
} while (0)
#define CUDA_TRY(call) \
do { \
cudaError_t result; \
if ((result = (call)) != cudaSuccess) { \
std::cerr << __FILE__ << ":" << __LINE__ << ": " \
<< cudaGetErrorName(result) << "\n"; \
return 1; \
} \
} while (0)
int main()
{
Sanitizer_SubscriberHandle handle;
SANITIZER_TRY(sanitizerSubscribe(&handle, sanitizer_callback, NULL));
SANITIZER_TRY(
sanitizerEnableDomain(1, handle, SANITIZER_CB_DOMAIN_RESOURCE));
void* dev_ptr;
CUDA_TRY(cudaMalloc(&dev_ptr, 10));
if (!malloc_called) {
std::cerr << "cudaMalloc() did not invoke callback\n";
return 1;
}
CUDA_TRY(cudaFree(dev_ptr));
if (!free_called) {
std::cerr << "cudaFree() did not invoke callback\n";
return 1;
}
SANITIZER_TRY(sanitizerUnsubscribe(handle));
return 0;
}
+1
View File
@@ -41,6 +41,7 @@ if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA STREQUAL "Clang")
endif()
add_cuda_test_macro(CudaOnly.DeviceLTO CudaOnlyDeviceLTO)
add_cuda_test_macro(CudaOnly.Sanitizer ${CMAKE_CTEST_COMMAND} --output-on-failure)
if(MSVC)
# Tests for features that only work with MSVC
+20
View File
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 4.3)
project(Sanitizer CUDA)
enable_testing()
# Goal for this example:
# Validate that we can use CUDAToolkit sanitizer
find_package(CUDAToolkit REQUIRED)
if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.1)
add_executable(CudaOnlySanitizer test_sanitizer.cu)
target_link_libraries(CudaOnlySanitizer PRIVATE CUDA::sanitizer)
add_test(NAME CudaOnlySanitizer COMMAND CudaOnlySanitizer)
if(WIN32)
get_property(sanitizer_path TARGET CUDA::sanitizer PROPERTY IMPORTED_LOCATION)
get_filename_component(sanitizer_dir "${sanitizer_path}" DIRECTORY)
set_property(TEST CudaOnlySanitizer PROPERTY ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:${sanitizer_dir}")
endif()
endif()
@@ -0,0 +1 @@
#include "../../Cuda/Sanitizer/test_sanitizer.cpp"