cuda-memcheck 无法检测 R 包中的内存泄漏

cuda-memcheck fails to detect memory leak in an R package

我正在构建 CUDA 加速的 R 包,我想使用 cuda-memcheck 进行调试。因此,在 this minimal example(在 deliberate_memory_leak GitHub 分支中),我通过注释掉对 cudaFree 的必要调用,在 someCUDAcode.c 中创建内存泄漏。然后,我看看cuda-memcheck能不能找到漏洞

$ cuda-memcheck --leak-check full  Rscript -e 'library(rcppcuda); hello()'
========= CUDA-MEMCHECK
An object of class "MyClass"
Slot "x":
 [1]  1  2  3  4  5  6  7  8  9 10

Slot "y":
 [1]  1  2  3  4  5  6  7  8  9 10

[1] "Object changed."
An object of class "MyClass"
Slot "x":
 [1] 500   2   3   4   5   6   7   8   9  10

Slot "y":
 [1]    1 1000    3    4    5    6    7    8    9   10

========= LEAK SUMMARY: 0 bytes leaked in 0 allocations
========= ERROR SUMMARY: 0 errors
$

运气不好。然后我在R extensions manual中看到R -d "valgrind --tool=memcheck --leak-check=full" --vanilla < mypkg-Ex.R才是正确的使用方法valgrind。所以我用 library(rcppcuda); hello() 创建了一个 test.R 文件并尝试了这个。

R -d "cuda-memcheck --leak-check full" --vanilla < test.R
*** Further command line arguments ('--vanilla ') disregarded
*** (maybe use 'run --vanilla ' from *inside* cuda-memcheck --leak-check full)

========= CUDA-MEMCHECK
Fatal error: you must specify '--save', '--no-save' or '--vanilla'
========= LEAK SUMMARY: 0 bytes leaked in 0 allocations
========= ERROR SUMMARY: 0 errors

最后,

$ cuda-memcheck --leak-check full R --vanilla < test.R
========= CUDA-MEMCHECK

R version 3.2.0 (2015-04-16) -- "Full of Ingredients"
Copyright (C) 2015 The R Foundation for Statistical Computing
Platform: x86_64-unknown-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> library(rcppcuda); hello()
An object of class "MyClass"
Slot "x":
 [1]  1  2  3  4  5  6  7  8  9 10

Slot "y":
 [1]  1  2  3  4  5  6  7  8  9 10

[1] "Object changed."
An object of class "MyClass"
Slot "x":
 [1] 500   2   3   4   5   6   7   8   9  10

Slot "y":
 [1]    1 1000    3    4    5    6    7    8    9   10

> 
========= LEAK SUMMARY: 0 bytes leaked in 0 allocations
========= ERROR SUMMARY: 0 errors
$

是否可以使 cuda-memcheck 用于 R 包?我知道我以为我已经弄明白了 here,但那时候,我并没有真正验证 cuda-memcheck 给我的答案。

这不是有效的 CUDA 代码:

extern "C" void someCUDAcode() {
  int a;
  CUDA_CALL(cudaMalloc((void**) &a, sizeof(int)));
  mykernel<<<1, 1>>>(1);
//  CUDA_CALL(cudaFree(&a));
}
  1. 当我们想做一个cudaMalloc操作时,我们在C中使用指针,而不是普通的变量,像这样:

      int *a;
      CUDA_CALL(cudaMalloc((void**) &a, sizeof(int)));
    
  2. 当我们想要释放之前分配的指针时,我们只传递指针,而不是它的地址:

    CUDA_CALL(cudaFree(a));
    
  3. 最后,cuda-memcheck(cuda-memcheck --help)的命令行帮助表示:

    --leak-check <full|no> [Default : no]

    Print leak information for CUDA allocations.

    NOTE: Program must end with cudaDeviceReset() for this to work.

documentation 中也有类似的注释。)

我认为第 3 项是您的代码中缺少的关键要素。对您的代码进行以下修改会为我生成正确的报告:

$ cat t786.cu
#include <stdio.h>

#define CUDA_CALL(x) {if((x) != cudaSuccess){ \
  printf("CUDA error at %s:%d\n",__FILE__,__LINE__); \
  printf("  %s\n", cudaGetErrorString(cudaGetLastError()));}}

__global__ void mykernel(int a){
  int id = threadIdx.x;
  int b = a;
  b++;
  id++;
}

int main() {
  int *a;
  CUDA_CALL(cudaMalloc((void**) &a, sizeof(int)));
  mykernel<<<1, 1>>>(1);
//  CUDA_CALL(cudaFree(a));
  cudaDeviceReset();
}
$ nvcc -o t786 t786.cu
$ cuda-memcheck --leak-check full ./t786
========= CUDA-MEMCHECK
========= Leaked 4 bytes at 0x402500000
=========     Saved host backtrace up to driver entry point at cudaMalloc time
=========     Host Frame:/lib64/libcuda.so.1 (cuMemAlloc_v2 + 0x17f) [0x13629f]
=========     Host Frame:./t786 [0x2dbb3]
=========     Host Frame:./t786 [0x610b]
=========     Host Frame:./t786 [0x3deaf]
=========     Host Frame:./t786 [0x2646]
=========     Host Frame:/lib64/libc.so.6 (__libc_start_main + 0xf5) [0x21d65]
=========     Host Frame:./t786 [0x2539]
=========
========= LEAK SUMMARY: 4 bytes leaked in 1 allocations
========= ERROR SUMMARY: 0 errors
$