我有四个数组:
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。
答案 0 :(得分: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
。
然后,我们可以使用thrust::inclusive_scan数组作为键,并使用thrust::reduce_by_key选择与每个顶点对应的neighborhood
中的值列于degree
的每个neighborhood
。
然后,我们只需要将adjacency
添加到步骤2中生成的中间degree
结果中。我们可以使用thrust::permutation_iterator。
这是一个完整的例子:
degree_summation
(删除我之前的其余错误。我建议的替代方法无效。)