/** * Grab pivot's adjacency list into memory. */ int grab_adj(graphchi_vertex<uint32_t, uint32_t> &v) { if(is_pivot(v.id())) { int ncount = v.num_edges(); // Count how many neighbors have larger id than v v.sort_edges_indirect(); int actcount = 0; vid_t lastvid = 0; for(int i=0; i<ncount; i++) { if (v.edge(i)->vertexid > v.id() && v.edge(i)->vertexid != lastvid) actcount++; // Need to store only ids larger than me lastvid = v.edge(i)->vertex_id(); } // Allocate the in-memory adjacency list, using the // knowledge of the number of edges. dense_adj dadj = dense_adj(actcount, (vid_t*) calloc(sizeof(vid_t), actcount)); actcount = 0; lastvid = 0; for(int i=0; i<ncount; i++) { if (v.edge(i)->vertexid > v.id() && v.edge(i)->vertexid != lastvid) { // Need to store only ids larger than me dadj.adjlist[actcount++] = v.edge(i)->vertex_id(); } lastvid = v.edge(i)->vertex_id(); } assert(dadj.count == actcount); adjs[v.id() - pivot_st] = dadj; assert(v.id() - pivot_st < adjs.size()); __sync_add_and_fetch(&grabbed_edges, actcount); return actcount; } return 0; }
/** * Vertex update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType> &v, graphchi_context &gcontext) { if (gcontext.iteration % 2 == 0) { adjcontainer->grab_adj(v); } else { uint32_t oldcount = v.get_data(); uint32_t newcounts = 0; v.sort_edges_indirect(); vid_t lastvid = 0; /** * Iterate through the edges, and if an edge is from a * pivot vertex, compute intersection of the relevant * adjacency lists. */ for(int i=0; i<v.num_edges(); i++) { graphchi_edge<uint32_t> * e = v.edge(i); if (e->vertexid > v.id() && e->vertexid >= adjcontainer->pivot_st) { assert(!is_deleted_edge_value(e->get_data())); if (e->vertexid != lastvid) { // Handles reciprocal edges (a->b, b<-a) if (adjcontainer->is_pivot(e->vertexid)) { uint32_t pivot_triangle_count = adjcontainer->intersection_size(v, e->vertexid, i); newcounts += pivot_triangle_count; /* Write the number of triangles into edge between this vertex and pivot */ if (pivot_triangle_count == 0 && e->get_data() == 0) { /* ... or remove the edge, if the count is zero. */ v.remove_edge(i); } else { e->set_data(e->get_data() + pivot_triangle_count); } } else { break; } } lastvid = e->vertexid; } assert(newcounts >= 0); } if (newcounts > 0) { v.set_data(oldcount + newcounts); } } /* Collect triangle counts matched by vertices with id lower than his one, and delete */ if (gcontext.iteration % 2 == 0) { int newcounts = 0; for(int i=0; i < v.num_edges(); i++) { graphchi_edge<uint32_t> * e = v.edge(i); if (e->vertexid < v.id()) { newcounts += e->get_data(); e->set_data(0); // This edge can be now deleted. Is there some other situations we can delete? if (v.id() < adjcontainer->pivot_st && e->vertexid < adjcontainer->pivot_st) { v.remove_edge(i); } } } v.set_data(v.get_data() + newcounts); } }