只能使用CUDA中的新运算符分配有限的内存

Only able to allocate limited memory using new operator in CUDA

本文关键字:分配 运算符 内存 CUDA      更新时间:2023-10-16

我写了一个类似的cuda内核

__global__ void mykernel(int size; int * h){
double *x[size];
for(int i = 0; i < size; i++){
  x[i] = new double[2];
}
h[0] = 20;
}
void main(){
  int size = 2.5 * 100000 // or 10,000
  int *h = new int[size];
  int *u;
  size_t sizee = size * sizeof(int);
  cudaMalloc(&u, sizee);
  mykernel<<<size, 1>>>(size, u);
  cudaMemcpy(&h, &u, sizee, cudaMemcpyDeviceToHost);
  cout << h[0];
}

我在内核中也有一些其他代码,但我已经注释掉了。上面的代码还分配了更多的内存。

现在,当我用size=2.5*10^5运行这个时,我得到h[0]值为0;

当我用size=100*100运行这个时,我得到h[0]值为20;

所以我猜测我的内核正在崩溃,因为我的内存不足。我正在使用一个特斯拉卡C2075,它有内存2GB!我甚至尝试过关闭xserver。我正在做的甚至不是100亿字节的数据。

如何为每个块分配更多内存?

现在,当我用size=2.5*10^5运行这个时,我得到h[0]值为0;

当我用size=100*100运行这个时,我得到h[0]值为20;

在您的内核启动中,您也使用这个size变量:

mykernel<<<size, 1>>>(size, u);
           ^^^^

在cc2.0设备(Tesla C2075)上,1D情况下的此特定参数限制为65535。所以2.5*10^5超过65535,但100*100没有。因此,如果您指定size为100*100,那么您的内核可能正在运行,但如果指定size为2.5*10^5,则可能不会运行。

正如已经向您建议的那样,正确的cuda错误检查应该向您指出这个错误,通常情况下,您可能需要在SO上提出更少的问题,并在SO上发布更高质量的问题。利用cuda运行时的功能,让您知道什么时候出了问题,什么时候犯了错误。这样你就不会陷入困境,以为你有内存分配问题,而实际上你可能有内核启动配置问题。

如何为每个块分配更多内存?

尽管这可能不是您的主要问题(如上所述),但在内核中,newmalloc仅限于设备堆的大小。一旦用完,对newmalloc的进一步调用将返回一个空指针。如果使用这个空指针,内核代码将开始执行未指定的行为,并且很可能崩溃。

当使用newmalloc时,尤其是在遇到问题时,检查空返回值是一种很好的做法。这适用于主机(至少对于malloc)和设备代码。

设备堆的大小从一开始就很小(8MB),但它可以修改。

参考文件:

设备内存堆有一个固定的大小,在将任何使用malloc()或free()的程序加载到上下文中之前,必须指定该大小。如果任何程序在未明确指定堆大小的情况下使用malloc(),则会分配默认的8兆字节堆。

以下API函数获取并设置堆大小:

•cudaDeviceGetLimit(size_t*size,cudaLimitMallocHeapSize)

•cudaDeviceSetLimit(cudaLimitMallocHeapSize,size_t-size)

授予的堆大小将至少为大小字节。cuCtxGetLimit()和cudaDeviceGetLimit()返回当前请求的堆大小。