process_edges函数
有六个参数:sparse_signal, sparse_slot, dense_signal, dense_slot,活跃点集合和dense_selective
pagegraph.cpp:
把next数组置空。next和curr负责存放上一轮和本轮顶点值
for (int i_i=0;i_i<iterations;i_i++) {
if (graph->partition_id==0) {
printf("delta(%d)=%lf\n", i_i, delta);
}
VertexId activated = 0;
graph->fill_vertex_array(next, (double)0);
graph.hpp:
process_edges原函数如下:
// process edges
template<typename R, typename M>
R process_edges(std::function<void(VertexId)> sparse_signal, std::function<R(VertexId, M, VertexAdjList<EdgeData>)> sparse_slot, std::function<void(VertexId, VertexAdjList<EdgeData>)> dense_signal, std::function<R(VertexId, M)> dense_slot, Bitmap * active, Bitmap * dense_selective = nullptr) {
double stream_time = 0;
stream_time -= MPI_Wtime();
对于每个线程分配缓存空间
for (int t_i=0;t_i<threads;t_i++) {
local_send_buffer[t_i]->resize( sizeof(MsgUnit<M>) * local_send_buffer_limit );
local_send_buffer[t_i]->count = 0;
}
下面调用了process_vertices这个函数
R reducer = 0;
EdgeId active_edges = process_vertices<EdgeId>(
[&](VertexId vtx){
return (EdgeId)out_degree[vtx];
},
active
);
bool sparse = (active_edges < edges / 20);
if (sparse) {
for (int i=0;i<partitions;i++) {
for (int s_i=0;s_i<sockets;s_i++) {
recv_buffer[i][s_i]->resize( sizeof(MsgUnit<M>) * (partition_offset[i+1] - partition_offset[i]) * sockets );
send_buffer[i][s_i]->resize( sizeof(MsgUnit<M>) * owned_vertices * sockets );
send_buffer[i][s_i]->count = 0;
recv_buffer[i][s_i]->count = 0;
}
}
} else {
for (int i=0;i<partitions;i++) {
for (int s_i=0;s_i<sockets;s_i++) {
recv_buffer[i][s_i]->resize( sizeof(MsgUnit<M>) * owned_vertices * sockets );
send_buffer[i][s_i]->resize( sizeof(MsgUnit<M>) * (partition_offset[i+1] - partition_offset[i]) * sockets );
send_buffer[i][s_i]->count = 0;
recv_buffer[i][s_i]->count = 0;
}
}
}
size_t basic_chunk = 64;
if (sparse) {
#ifdef PRINT_DEBUG_MESSAGES
if (partition_id==0) {
printf("sparse mode\n");
}
#endif
int * recv_queue = new int [partitions];
int recv_queue_size = 0;
std::mutex recv_queue_mutex;
current_send_part_id = partition_id;
#pragma omp parallel for
for (VertexId begin_v_i=partition_offset[partition_id];begin_v_i<partition_offset[partition_id+1];begin_v_i+=basic_chunk) {
VertexId v_i = begin_v_i;
unsigned long word = active->data[WORD_OFFSET(v_i)];
while (word != 0) {
if (word & 1) {
sparse_signal(v_i);
}
v_i++;
word = word >> 1;
}
}
#pragma omp parallel for
for (int t_i=0;t_i<threads;t_i++) {
flush_local_send_buffer<M>(t_i);
}
recv_queue[recv_queue_size] = partition_id;
recv_queue_mutex.lock();
recv_queue_size += 1