Я пишу код, пытающийся использовать рекурсию, чтобы найти узел 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 для простоты.