我的任務是使用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。 –