如何结合使用thrust和valgrind来检测内存泄漏?

alf*_*lfC 5 c++ valgrind memory-leaks cuda thrust

有没有办法将 CUDA Thrust 库与 Valgrind 内存泄漏检查器一起使用?

我问的原因是因为这个简单的程序:

#include <thrust/device_vector.h>

int main(){
    thrust::device_vector<int> D(5);
    assert( D.size() == 5 );
}
Run Code Online (Sandbox Code Playgroud)

编译为:

#include <thrust/device_vector.h>

int main(){
    thrust::device_vector<int> D(5);
    assert( D.size() == 5 );
}
Run Code Online (Sandbox Code Playgroud)

使 Valgrind 相信存在多种可能的内存泄漏。

我知道它们一定是误报,而且 valgrind 不是用来检测 GPU 内存泄漏的,但我想知道是否有一个标志或标准方法可以使这两个工具一起工作(例如检测 CPU 内存泄漏)。

如果有一套标准的 Valgrind 异常,我会很乐意使用它们,但我想在玩 wack-a-mole 之前先问一下。

$ /usr/local/cuda-11.1/bin/nvcc device_vector.cu -o device_vector.cu.x
Run Code Online (Sandbox Code Playgroud)

提到的自述文件README_MISSING_SYSCALL_OR_IOCTL对我来说不是很有帮助。


添加注释:CUDA 附带了一个名为 memchecker 的 memchecker cuda-memcheck,它不会报告上面程序中的内存泄漏,但它似乎不能替代 valgrind,因为它不会检测简单 cpu 程序中的实际内存泄漏:

#include <thrust/device_vector.h>

int main(){
//  thrust::device_vector<int> D(5);
//  assert( D.size() == 5 );
    
//  cudaDeviceSynchronize();
    std::allocator<int> alloc;
    int* p = alloc.allocate(10);
    p[0] = 2;
    return p[0];
}
Run Code Online (Sandbox Code Playgroud)

alf*_*lfC 2

.valgrind-supressions目前我正在项目的根目录中使用此抑制文件:

{
   <suppression_for_thrust_allocations>
   Memcheck:Leak
   match-leak-kinds: possible
   fun:*alloc
   ...
   obj:*libcuda.so.*
   ...
   obj:*libcuda.so.*
   fun:__cudart*
   ...
   fun:__cudart*
   fun:cudaMalloc
   fun:_ZN6thrust6system4cuda6detail20cuda_memory_resourceIXadL_Z10cudaMallocEEXadL_Z8cudaFreeEENS_8cuda_cub7pointerIvEEE11do_allocateEmm
   ...
}
Run Code Online (Sandbox Code Playgroud)

(三个点是实际代码)

通过删除这条_ZN6thrust线也许它可以更普遍,但我不想过早地概括抑制。

需要注意的是,这并不是检查 GPU 中的泄漏,因为这cuda-memcheck是必要的。


更新:我将抑制范围扩大到 1) 包括生成的案例cudaMallocManaged2) 由 CUDA 运行时引起,没有推力分配器的参与(如 @RobertCrovella 提到的)。

{
   <suppression_for_cudaMalloc_and_cudaMallocManaged_allocations>
   Memcheck:Leak
   match-leak-kinds: possible
   fun:*alloc
   ...
   obj:*libcuda.so.*
   ...
   obj:*libcuda.so.*
   fun:__cudart*
   ...
   fun:__cudart*
   fun:cudaMalloc*
   ...
}
Run Code Online (Sandbox Code Playgroud)

我正在CMakeLists.txt使用这些选项来实际使用上面列出的抑制文件

  ...
set(MEMORYCHECK_COMMAND_OPTIONS "-q --tool=memcheck --leak-check=yes --num-callers=52 --trace-children=yes --leak-check=full --track-origins=yes --gen-suppressions=all") # must go before `include(CTest)`
set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/.valgrind-suppressions") # must go before `include(CTest)`

include(CTest)
  ...
Run Code Online (Sandbox Code Playgroud)

(这里的三个点代表文件的其余部分)

欢迎对这种抑制模式进行改进。


作为参考,完整自动生成的抑制valgrind如下所示:

{
   <insert_a_suppression_name_here>
   Memcheck:Leak
   match-leak-kinds: possible
   fun:calloc
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   obj:/usr/lib/x86_64-linux-gnu/libcuda.so.470.63.01
   fun:__cudart764
   fun:__cudart763
   fun:__cudart768
   fun:__cudart941
   fun:__cudart607
   fun:cudaMalloc
   fun:_ZN6thrust6system4cuda6detail20cuda_memory_resourceIXadL_Z10cudaMallocEEXadL_Z8cudaFreeEENS_8cuda_cub7pointerIvEEE11do_allocateEmm
   fun:_ZN6thrust26device_ptr_memory_resourceINS_6system4cuda6detail20cuda_memory_resourceIXadL_Z10cudaMallocEEXadL_Z8cudaFreeEENS_8cuda_cub7pointerIvEEEEE11do_allocateEmm
   fun:_ZN6thrust2mr9allocatorIiNS_26device_ptr_memory_resourceINS_6system4cuda6detail20cuda_memory_resourceIXadL_Z10cudaMallocEEXadL_Z8cudaFreeEENS_8cuda_cub7pointerIvEEEEEEE8allocateEm
   fun:_ZZN6thrust6detail16allocator_traitsINS_16device_allocatorIiEEE8allocateERS3_mEN19workaround_warnings8allocateES5_m
   fun:_ZN6thrust6detail16allocator_traitsINS_16device_allocatorIiEEE8allocateERS3_m
   fun:_ZN6thrust6detail18contiguous_storageIiNS_16device_allocatorIiEEE8allocateEm
   fun:_ZN6thrust6detail11vector_baseIiNS_16device_allocatorIiEEE17allocate_and_copyINS0_15normal_iteratorIPKiEEEEvmT_SA_RNS0_18contiguous_storageIiS3_EE
   fun:_ZN6thrust6detail11vector_baseIiNS_16device_allocatorIiEEE10range_initINS0_15normal_iteratorIPKiEEEEvT_SA_NS_27random_access_traversal_tagE
   fun:_ZN6thrust6detail11vector_baseIiNS_16device_allocatorIiEEE10range_initINS0_15normal_iteratorIPKiEEEEvT_SA_
   fun:_ZN6thrust6detail11vector_baseIiNS_16device_allocatorIiEEEC1IiSaIiEEERKNS1_IT_T0_EE
   fun:_ZN6thrust13device_vectorIiNS_16device_allocatorIiEEEC1IiSaIiEEERKNS_11host_vectorIT_T0_EE
   fun:_ZN6vector11test_methodEv
   fun:_ZL14vector_invokerv
   fun:_ZN5boost6detail8function22void_function_invoker0IPFvvEvE6invokeERNS1_15function_bufferE
   obj:/usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.74.0
   fun:_ZN5boost17execution_monitor13catch_signalsERKNS_8functionIFivEEE
   fun:_ZN5boost17execution_monitor7executeERKNS_8functionIFivEEE
   fun:_ZN5boost17execution_monitor8vexecuteERKNS_8functionIFvvEEE
   fun:_ZN5boost9unit_test19unit_test_monitor_t21execute_and_translateERKNS_8functionIFvvEEEm
   obj:/usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.74.0
   obj:/usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.1.74.0
   fun:_ZN5boost9unit_test9framework3runEmb
   fun:_ZN5boost9unit_test14unit_test_mainEPFbvEiPPc
   fun:main
}
Run Code Online (Sandbox Code Playgroud)