在cuda中递归构造二叉树
我想在向量s.t.中建立一个二叉树。父节点的值是它的两个子节点的和。在C中递归构建树的步骤如下所示:在cuda中递归构造二叉树,cuda,Cuda,我想在向量s.t.中建立一个二叉树。父节点的值是它的两个子节点的和。在C中递归构建树的步骤如下所示: int construct(int elements[], int start, int end, int* tree, int index) { if (start == end) { tree[index] = elements[start]; return tree[index]; } int middle = start + (en
int construct(int elements[], int start, int end, int* tree, int index) {
if (start == end) {
tree[index] = elements[start];
return tree[index];
}
int middle = start + (end - start) / 2;
tree[index] = construct(elements, start, middle, tree, index*2) +
construct(elements, middle, end, tree, index*2+1);
return tree[index];
}
但我不知道如何利用线程以并行方式在CUDA中构建它。我发现一个有用的方法是
我们应该如何并行化这种递归算法?一种方法是使用Garanzha等人提出的方法,从根开始依次处理节点级别。其思想是以广度优先的顺序保持不断增长的节点阵列,以便层次结构中的每一层对应于线性范围的节点。在给定的级别上,我们为属于此范围的每个节点启动一个线程。线程首先从节点数组读取第一个和最后一个,然后调用findSplit()。然后,它使用原子计数器将生成的子节点附加到同一节点数组中,并写出相应的子范围。该过程进行迭代,以便每个级别输出下一级别上包含的节点,然后在下一轮中进行处理
它按顺序处理每个级别,并并行化每个级别的节点。我认为这完全有道理,但我不知道如何准确地实现这一点,有人能给我一个如何做到这一点的想法或例子吗?我不确定上述索引方案是否可行 下面是一个可以工作的示例代码:(尽管树索引可能不适合您的需要): 构建整个树需要多次调用buildtreelevel内核:
int buildtree (int grid, int block, const int* d_elements, int count, int** h_tree, int* d_data)
{
const int* ptr_elements = d_elements ;
int* ptr_data = d_data ;
int level = 0 ;
int levelcount = count ;
while (levelcount > 1)
{
buildtreelevel <<< grid, block >>> (ptr_elements, levelcount, ptr_data) ;
levelcount = (levelcount + 1) >> 1 ;
h_tree [level++] = ptr_data ;
ptr_elements = ptr_data ;
ptr_data += levelcount ;
}
return level ;
}
树结构存储在h_树中,h_树是设备指针的主机数组
这不是最优的,但可能是一个良好的开端(使用带ldg的对齐int4),一次处理4个级别可能会提高性能
int treesize (int count, int& maxlevel)
{
int res = 1 ;
while (count > 1)
{
count = (count + 1) >> 1 ;
res += count ;
++maxlevel;
}
return res ;
}
int buildtree (int grid, int block, const int* d_elements, int count, int** h_tree, int* d_data)
{
const int* ptr_elements = d_elements ;
int* ptr_data = d_data ;
int level = 0 ;
int levelcount = count ;
while (levelcount > 1)
{
buildtreelevel <<< grid, block >>> (ptr_elements, levelcount, ptr_data) ;
levelcount = (levelcount + 1) >> 1 ;
h_tree [level++] = ptr_data ;
ptr_elements = ptr_data ;
ptr_data += levelcount ;
}
return level ;
}
int main()
{
int nElements = 10000000 ;
int* d_elements ;
int* d_data ;
int** h_tree ;
int maxlevel = 1 ;
cudaMalloc ((void**)&d_elements, nElements * sizeof (int)) ;
cudaMalloc ((void**)&d_data, treesize(nElements, maxlevel) * sizeof (int)) ;
h_tree = new int*[maxlevel];
buildtree (64, 256, d_elements, nElements, h_tree, d_data) ;
cudaError_t res = cudaDeviceSynchronize() ;
if (cudaSuccess != res)
fprintf (stderr, "ERROR (%d) : %s \n", res, cudaGetErrorString(res));
cudaDeviceReset();
}