在cuda中递归构造二叉树

在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

我想在向量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 + (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();
}