При рекурсии обнаружен недопустимый доступ к памяти при использовании CUDA - PullRequest
0 голосов
/ 22 апреля 2020

Я пишу код, пытающийся использовать рекурсию, чтобы найти узел root для некоторых точек в изображении PCL. Поскольку CUDA обладает отличными возможностями параллельных вычислений, я решил использовать GPGPU для достижения рекурсии. Как правило, каждый поток соответствует узлу (я знаю, что произвольный доступ к памяти не подходит для GPU, но я все еще хочу попробовать). Однако я столкнулся с недопустимым доступом к памяти в функции ядра. Я думал, что проблема в том, что стек потоков не был достаточно большим для большой глубины рекурсии, но все еще существовала та же проблема, что и при изменении размера стека с 1 КБ до 100 КБ. Ребята, вы понимаете, почему появилась эта проблема? Мой код выглядит следующим образом.
Код устройства здесь:

inline __device__ Node* dev_DisjointSetFindRecursive(Node *&x){
    if (x->parent != x) {
        x->parent = dev_DisjointSetFindRecursive(x->parent);
      }
      return x->parent;
}

__device__ Node* dev_DisjointSetFind(Node *x){
    Node *y = x->parent;
    if (y == x || y->parent == y) {
        return y;
    }
    //Node *root = nullptr;
    Node *root = dev_DisjointSetFindRecursive(y->parent);
    x->parent = root;
    y->parent = root;
    return root;
}

inline __device__ void dev_DisjointSetMerge(Node *x, const Node *y){

}

__device__ void dev_DisjointSetUnion(Node* x, Node* y){
    x = dev_DisjointSetFind(x);
    y = dev_DisjointSetFind(y);
    if (x == y) {
    return;
    }
    if (x->node_rank < y->node_rank) {
    x->parent = y;
    dev_DisjointSetMerge(y, x);
    } else if (y->node_rank < x->node_rank) {
    y->parent = x;
    dev_DisjointSetMerge(x, y);
    } else {
    y->parent = x;
    x->node_rank++;
    dev_DisjointSetMerge(x, y);
    }
}

Глобальное ядро ​​здесь:

__global__ void cuda_node_traverse_b(Node* nodes , int rows_, int cols_){
            int row = i / cols_;
            int col = i % cols_;
            int row = blockIdx.x;
            int col = threadIdx.x;
            int grid = row * cols_ + col;
            Node *node = &nodes[grid];
            if (!node->is_center)
            {

            }
            else{
                for (int row2 = row - 1 ; row2 <= row + 1; ++row2)
                {
                    for (int col2 = col - 1; col2 <= col + 1; ++col2)
                    {
                        if ((row2 == row || col2 == col) && dev_IsValidRowCol(row2, col2, rows_, cols_))
                        {
                            int grid2 = row2 * cols_ + col2;
                            Node *node2 = &nodes[grid2];
                            if (node2->is_center)
                            {
                                dev_DisjointSetUnion(node, node2);
                            }
                        }
                    }

                }
            }




}

Я запустил его:

cuda_node_traverse_b<<<512,512>>>(nodes, rows_, cols_);

Как я закомментировал функцию dev_DisjointSetFindRecursive, больше не было незаконного доступа к памяти. Кстати, я опускаю некоторый код как dev_IsValidRowCol для простоты.

...