【发布时间】:2021-12-29 14:22:26
【问题描述】:
我正在尝试在我的设备内、线程内和块内初始化复杂对象。在我看来,cudaDeviceSetLimit 有问题。鉴于我对问题的理解,我没有正确设置每个线程的堆内存量。 documentation的这一部分是指我的问题。但它们不初始化对象。我也阅读了this post,但无法让我的代码正常工作。
编辑
与第一个答案相反:在我的问题配置中必须在内核中执行此操作,因为我想利用并行跨块初始化对象的优势。
我制作了以下玩具示例,它适用于少量块 (65),但不适用于 65535 个块(我可以在我的设备上使用的最大块数):
class NNode{
public:
int node_id;
};
class cuNetwork{
public:
int num_allnodes;
NNode** all_nodes;
};
__global__ void mallocTest(int num_allnodes, cuNetwork** arr_gpu_net){
int bId = blockIdx.x;
cuNetwork* gpu_net = new cuNetwork();
gpu_net->all_nodes = new NNode*[num_allnodes];
for(int i=0; i<num_allnodes; i++){
gpu_net->all_nodes[i] = new NNode();
}
arr_gpu_net[bId] = gpu_net;
}
int main(int argc, const char **argv){
int numBlocks = 65;
int num_allnodes = 200;
cuNetwork** arr_gpu_net = new cuNetwork*[numBlocks];
cudaMalloc((void **)&arr_gpu_net, sizeof(cuNetwork*) * numBlocks);
size_t size;
//for each block
size = sizeof(cuNetwork);//new cuNetwork()
size += sizeof(NNode*) * num_allnodes;//new NNode*[num_allnodes]
size += sizeof(NNode) * num_allnodes; //for()... new NNode()
//size = sizeof(cuNetwork) + (sizeof(int) * 2 + sizeof(NNode)) * num_allnodes;
cudaDeviceSetLimit(cudaLimitMallocHeapSize, numBlocks * size);
mallocTest<<<numBlocks, 1>>>(num_allnodes, arr_gpu_net);
cudaDeviceSynchronize();
return 0;
}
一旦我开始向对象添加其他属性,或者如果我将 numBlocks 增加到 65535,我就会收到错误消息:
CUDA Exception: Warp Illegal Address
The exception was triggered at PC 0x555555efff90
Thread 1 "no_fun" received signal CUDA_EXCEPTION_14, Warp Illegal Address.
[Switching focus to CUDA kernel 0, grid 1, block (7750,0,0), thread (0,0,0), device 0, sm 1, warp 3, lane 0]
0x0000555555f000b0 in mallocTest(int, cuNetwork**)<<<(65535,1,1),(1,1,1)>>> ()
我的问题是:在这个例子中,我应该如何正确初始化cudaDeviceSetLimit,以便获得cuNetwork 的每个线程初始化所需的正确内存量?
【问题讨论】:
-
您正在对设备上的内存分配行为做出各种假设,这些假设可能不正确,尤其是对齐和粒度。调用 new n 次来创建 n 个对象将需要 n 倍于对象大小(以字节为单位)的想法几乎永远不会正确
标签: c++ oop cuda heap-memory