我的任务是使用CUDA在高维数据结构中实现最近邻居搜索。我正在使用递归搜索,以便在树中进行有效的搜索。但首先我试图在递归函数中访问数据结构中的3d点并计算它们之间的距离。但也有遇到过,当我计算点之间的距离在数据结构的一个非法的内存访问:从CUDA递归函数中的结构访问数据失败,导致非法内存访问
float dist = (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]);
下面是完整的小例子:
struct Node {
int divfeat;
float divval;
int child1;
int child2;
Node() {
child1 = NULL;
child2 = NULL;
}
};
__global__
void gpuKernel(int veclen_ /*dimension*/, int size_ /*number of points*/, Node* devpool_ /*tree*/, float* devdataset_ /*points*/)
{
gpuRecursive(0, veclen_, size_, devpool_, devdataset_);
}
/* problems with recusive function */
__device__
void gpuRecursive(int index_,int veclen_, int size_, Node* devpool_, float* devdataset_)
{
/* if current Node has a valid children, call gpuRecursive for this child */
if (devpool_[index_].child1) { gpuRecursive(devpool_[index_].child1, veclen_, size_, devpool_, devdataset_); }
if (devpool_[index_].child2) { gpuRecursive(devpool_[index_].child2, veclen_, size_, devpool_, devdataset_);
/* if current node is a leaf do anything */
if (!devpool_[index_].child1 && !devpool_[index_].child2) {
if (devpool_[index_].divfeat != size_){
float* a = &devdataset_[devpool_[index_].divfeat*veclen_];
float* b = &devdataset_[devpool_[index_].divfeat*veclen_];
/* when computing dist an error occcurs */
float dist = (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]);
}
}
}
但是当我使用一个正常的功能没有任何递归访问是有效的I可以计算任意两个点之间的距离:
__device__
void gpuRegular(int index_,int veclen_, int size_ Node* devpool_, float* devdataset_)
{
for (int i = 0; i< size_; i++) {
ElementType* a = &devdataset_[i*veclen_];
ElementType* b = &devdataset_[(i+1)*veclen_];
/* when computing dist all works fine */
float dist = (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]);
}
}
另外,也可以在递归函数和c,以限定两个阵列注意它们之间的距离。这意味着在使用递归函数时,问题出在与全局内存通信的任何地方?
任何人都可以解释我在CUDA中使用递归函数时的这种行为。有没有可能绕过这个问题,并通过递归实现来解决搜索问题?
不应该在行尾加':if(devpool_ [index _]。child2)'? – Matso
那是正确的。我在这个论坛上编写代码时忘了它。但我的源代码没有任何失败(我希望:))。所描述的行为已经遇到了我一个星期,我已经尝试了很多,绕过它。 –
请提供[mcve]。内核本身并不是一个MCVE。 –