我写了一个这样的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来尝试这个。我正在做的工作甚至不是100mb的数据。
如何为每个块分配更多内存?
答案 0 :(得分:1)
现在当我运行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,则可能无法运行。
正如已经向您建议的那样,proper cuda error checking应该将此错误指向您,并且通常可能会导致您需要在SO上提出更少的问题,以及在SO上发布更高质量的问题。充分利用CUDA运行时的能力,让您知道出错的时间和出错的时间。然后你不会陷入困境,认为你有内存分配问题,实际上你可能有内核启动配置问题。
如何为每个块分配更多内存?
虽然这可能不是您的主要问题(如上所述),但内核中new
和malloc
仅限于设备堆的大小。一旦用尽,进一步调用new
或malloc
将返回空指针。如果你仍然使用这个空指针,你的内核代码将开始执行未指定的行为,并且可能会崩溃。
使用new
和malloc
时,尤其是当您遇到问题时,检查空返回值是一种很好的做法。这适用于主机(至少为malloc
)和设备代码。
设备堆的大小一开始就很小(8MB),但可以修改。
设备内存堆具有固定大小,必须在将任何使用malloc()或free()的程序加载到上下文之前指定。如果任何程序使用malloc()而未显式指定堆大小,则分配默认堆8兆字节。
以下API函数获取并设置堆大小:
•cudaDeviceGetLimit(size_t * size,cudaLimitMallocHeapSize)
•cudaDeviceSetLimit(cudaLimitMallocHeapSize,size_t size)
授予的堆大小至少为size个字节。 cuCtxGetLimit()和cudaDeviceGetLimit()返回当前请求的堆大小。