[英]Cuda complex object initialization within device: problem with cudaDeviceSetLimit
我正在尝试在我的设备内、线程内和块内初始化复杂对象。 在我看来, cudaDeviceSetLimit
有问题。 鉴于我对问题的理解,我没有正确设置每个线程的堆 memory 数量。 这部分文档是指我的问题。 但他们没有初始化 object。 我也读过这篇文章,但无法让我的代码正常工作。
编辑与第一个答案相反:在我的问题配置中必须在 kernel 内执行此操作,因为我想利用跨块并行初始化对象的优势
我制作了以下玩具示例,它适用于少量块(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
以获得正确数量的 memory 用于cuNetwork
的每个线程的初始化? 任何提示将不胜感激。 非常感谢您的帮助。
要回答您的问题:
由于 memory 填充和分配粒度,每个块可能需要比计算大小更多的 memory。 您应该始终检查new
的返回值。 如果是nullptr
,则分配失败。
但是,如果预先知道所有网络的节点总数,那么对所有节点(和所有网络)只使用cudaMalloc
的 memory 会更有效。 然后,在 kernel 中相应地更新指针。
像这样的东西:
struct cuNetwork2{
int num_allnodes;
NNode* all_nodes;
}
__global__ void kernel(cuNetwork2* d_networks, Node* d_nodes, int numNodesPerNetwork){
int index = ...
d_networks[index].num_allnodes = numNodesPerNetwork;
d_networks[index].all_nodes = d_nodes + index * numNodesperNetwork;
}
...
int numBlocks = 65;
int num_allnodes = 200;
cuNetwork2* d_networks;
NNode* d_nodes;
cudaMalloc(&d_networks, sizeof(cuNetwork2) * numBlocks);
cudaMalloc(&d_nodes, sizeof(NNode) * numBlocks * num_allnodes);
kernel<<<>>>(d_networks, d_nodes, num_allnodes);
在这种情况下,您不需要 cudaDeviceSetLimit 或内核内动态分配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.