在thrust-cuda中计算阵列的更快方法

时间:2014-12-01 13:48:13

标签: graph cuda thrust

我有四个数组:

thrust::device_vector<int> vertices;
thrust::device_vector<int> adjacency:
thrust::device_vector<int> degree_summation;
thrust::device_vector<int> degree;

顶点数组的索引表示图形的顶点,而其内容指向邻接数组中每个顶点的第一个邻居。数组度存储顶点中每个顶点的度数。

我希望degree_summation数组保持每个顶点的度数加上每个顶点邻域的度数之和。

Ex: Given the graph:
 0
/ \
1--2

vertices = {0,2,4}
adjacency = {1,2,0,2,0,1}
degree = {2,2,2}

我想要的是什么:

degree_summation = {6,6,6}

目前,我正在使用for循环来计算这个值,但我想也许有一种更快的方法来使用推力给出的基元来计算这些值。我用来计算degree_sumation数组的内核:

__global__ void computeDegreeSummation(int* vertices,int* adjacency,unsigned int* degree_summation, unsigned int * degree,unsigned int num_vertices, unsigned int num_edges){
unsigned long int tid = (gridDim.y*blockIdx.y+blockIdx.x)*blockDim.x+threadIdx.x;
if(tid < num_vertices){
    int pos_first_neighbor = vertices[tid];
    int pos_last_neighbor;
    if(tid != num_vertices - 1){
        int it = tid;
        pos_last_neighbor = vertices[it+1];
        while(pos_last_neighbor == 0){
            it++;
            pos_last_neighbor = vertices[it+1];
        }
        pos_last_neighbor--;
    }//if
    else{
        pos_last_neighbor = num_edges - 1;
    }//else
    for(int nid = pos_first_neighbor; nid <= pos_last_neighbor; nid++){
        if(adjacency[nid]!=tid){
            degree_summation[tid]+=degrees[adjacency[nid]];
        }//if
    }//for
}//if
}//kernel

因为我在计算内核之前用每个顶点的度数初始化了degree_summation,所以在for里面有一个if。

1 个答案:

答案 0 :(得分:1)

我不知道这是否会更快 - 因为我不知道你的参考实现有多快。但这是一种可能的方法:

  1. 创建一个向量,为每个顶点定义adjacency中的邻域。

    vertices =     {0,  2,  4}
    adjacency =    {1,2,0,2,0,1}
    neighborhood = {1,0,1,0,1,0}  (after scatter)
    neighborhood = {1,1,2,2,3,3}  (after inclusive scan)
    

    为实现此目的,我们会根据neighborhood提供的索引thrust::scatter将{1}(thrust::constant_iterator}一组放入vertices数组,然后执行{{} 3}} neighborhood

  2. 然后,我们可以使用thrust::inclusive_scan数组作为键,并使用thrust::reduce_by_key选择与每个顶点对应的neighborhood中的值列于degree的每个neighborhood

  3. 然后,我们只需要将adjacency添加到步骤2中生成的中间degree结果中。我们可以使用thrust::permutation_iterator

  4. 这是一个完整的例子:

    degree_summation

    (删除我之前的其余错误。我建议的替代方法无效。)