首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何计算内核中动态内存分配所需的堆大小?

如何计算内核中动态内存分配所需的堆大小?
EN

Stack Overflow用户
提问于 2017-08-21 17:29:25
回答 1查看 590关注 0票数 0

我面临的问题是,如果我将CUDA堆大小设置为需要在内核中分配的内存总量,堆仍然不足以为所有分配提供服务。

这是一个代表我的用例的最小示例:

代码语言:javascript
复制
#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堆测试

程序输出为

代码语言:javascript
复制
set heap size to 4608000
heap size is now 4653056
block 0, array 7 is NULL

因此,即使堆大小大于所需的大小,它也不够大。在这种情况下,如何正确计算所需的大小?

EN

Stack Overflow用户

发布于 2017-08-21 21:56:01

您可能无法计算应用程序堆所需的确切大小,因为您无法控制CUDA的内存管理器。就像在分配CPU内存时,你有操作系统的内存管理器,CUDA有它自己的内存管理器。当您在堆中分配多个数组时,您不能保证它们将完全适合堆的大小,可能存在一些开销。

为了举例说明,我对您的代码做了一个小的修改,以打印由malloc返回的内存地址:

代码语言:javascript
复制
printf("block %d, array %d is %p\n", blockIdx.x, i, arrS[i]);

这是我在我的GTX 1070上得到的:

代码语言:javascript
复制
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) * N576000字节。例如:

0x1020568f280 - 0x10205600120 = 586080字节(数组1)

0x10205738520 - 0x1020568f280 = 692896字节(数组2)

由于就传递给malloc()的块大小而言,这些块在内存中是连续的,因此我们可以验证确实存在一些不能分配576000字节块的内存块。在数组1和2之间,我们有额外的10080字节,在数组2和3之间,有额外的116896字节(这超过块大小的20%!)。

我要做的是避免在堆上动态分配内存,而是在主机代码执行期间分配它。但是,如果出于某种原因,您确实需要这样做,我建议您设置堆大小时留出一些开销余量,在看起来足够大之前对其进行测试。我至少预计,即使存在一些堆分配开销,这也不应该太大,所以可能会开始分配额外的10%,如果需要的话,从那里开始增加。

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45793665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档