繁体   English   中英

Cuda 复杂 object 设备内初始化:cudaDeviceSetLimit 问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM