我面临的问题是,如果我将CUDA堆大小设置为需要在内核中分配的内存总量,堆仍然不足以为所有分配提供服务。
这是一个代表我的用例的最小示例:
#include <stdio.h>
#define NARR 8
__global__
void heaptest(int N){
double* arr[NARR];
__shared__ double* arrS[NARR];
if(threadIdx.x == 0){
for(int i = 0; i < NARR; i++){
arrS[i] = (double*) malloc(sizeof(double) * N);
if(arrS[i] == NULL)
printf("block %d, array %d is NULL\n", blockIdx.x, i);
}
}
__syncthreads();
for(int i = 0; i < NARR; i++){
arr[i] = arrS[i];
}
}
size_t getHeapSizePerBlock(int N){
return sizeof(double) * N * NARR;
}
int main(){
int N = 4000 * 18;
int nBlocks = 1;
size_t myheapsize = getHeapSizePerBlock(N) * nBlocks;
printf("set heap size to %lu\n", myheapsize);
cudaDeviceSetLimit(cudaLimitMallocHeapSize, myheapsize);
size_t a;
cudaDeviceGetLimit(&a, cudaLimitMallocHeapSize);
printf("heap size is now %lu\n", a);
heaptest<<<nBlocks, 128>>>(N);
cudaDeviceSynchronize();
cudaDeviceReset();
return 0;
}我使用nvcc V8.0.61进行编译。
nvcc -arch=sm_60 heaptest.cu -o堆测试
程序输出为
set heap size to 4608000
heap size is now 4653056
block 0, array 7 is NULL因此,即使堆大小大于所需的大小,它也不够大。在这种情况下,如何正确计算所需的大小?
发布于 2017-08-21 21:56:01
您可能无法计算应用程序堆所需的确切大小,因为您无法控制CUDA的内存管理器。就像在分配CPU内存时,你有操作系统的内存管理器,CUDA有它自己的内存管理器。当您在堆中分配多个数组时,您不能保证它们将完全适合堆的大小,可能存在一些开销。
为了举例说明,我对您的代码做了一个小的修改,以打印由malloc返回的内存地址:
printf("block %d, array %d is %p\n", blockIdx.x, i, arrS[i]);这是我在我的GTX 1070上得到的:
block 0, array 0 is 0x102059a8d20
block 0, array 1 is 0x10205600120
block 0, array 2 is 0x1020568f280
block 0, array 3 is 0x10205738520
block 0, array 4 is 0x102057c7680
block 0, array 5 is 0x10205870920
block 0, array 6 is 0x102058ffa80
block 0, array 7 is (nil)首先要注意的是,内存位置并不(总是)连续/递增(例如,数组0>数组6> ... >数组1),但这对我们来说并不是太重要。此外,如果按降序减去内存地址,则不会得到传递给malloc()的大小,在本例中,大小始终为sizeof(double) * N或576000字节。例如:
0x1020568f280 - 0x10205600120 = 586080字节(数组1)
0x10205738520 - 0x1020568f280 = 692896字节(数组2)
由于就传递给malloc()的块大小而言,这些块在内存中是连续的,因此我们可以验证确实存在一些不能分配576000字节块的内存块。在数组1和2之间,我们有额外的10080字节,在数组2和3之间,有额外的116896字节(这超过块大小的20%!)。
我要做的是避免在堆上动态分配内存,而是在主机代码执行期间分配它。但是,如果出于某种原因,您确实需要这样做,我建议您设置堆大小时留出一些开销余量,在看起来足够大之前对其进行测试。我至少预计,即使存在一些堆分配开销,这也不应该太大,所以可能会开始分配额外的10%,如果需要的话,从那里开始增加。
https://stackoverflow.com/questions/45793665
复制相似问题