Skip to content

Commit

Permalink
Optimize clustering by ignoring computation of vertices that degree l…
Browse files Browse the repository at this point in the history
…ess than 2 (#1597)
  • Loading branch information
acezen committed Jun 8, 2022
1 parent 5ad8d52 commit 65523c6
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 85 deletions.
189 changes: 106 additions & 83 deletions analytical_engine/apps/clustering/clustering.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ class Clustering
[&messages, &frag, &ctx](int tid, vertex_t v) {
ctx.global_degree[v] =
frag.GetLocalOutDegree(v) + frag.GetLocalInDegree(v);
messages.SendMsgThroughEdges<fragment_t, int>(
frag, v, ctx.global_degree[v], tid);
if (ctx.global_degree[v] > 1) {
messages.SendMsgThroughEdges<fragment_t, int>(
frag, v, ctx.global_degree[v], tid);
}
});
messages.ForceContinue();
}
Expand All @@ -79,88 +81,90 @@ class Clustering

ForEach(inner_vertices.begin(), inner_vertices.end(),
[&frag, &ctx, &messages, &vertices](int tid, vertex_t v) {
vid_t u_gid, v_gid;
auto& nbr_vec = ctx.complete_neighbor[v];
int degree = ctx.global_degree[v];
nbr_vec.reserve(degree);
std::vector<std::pair<vid_t, uint32_t>> msg_vec;
msg_vec.reserve(degree);

typename FRAG_T::template vertex_array_t<uint32_t> is_rec;
is_rec.Init(vertices, 0);
auto es = frag.GetOutgoingAdjList(v);
for (auto& e : es) {
auto u = e.get_neighbor();
is_rec[u]++;
}
es = frag.GetIncomingAdjList(v);
for (auto& e : es) {
auto u = e.get_neighbor();
is_rec[u]++;
if (is_rec[u] == 2) {
ctx.rec_degree[v]++;
}
}
if (degree > 1) {
vid_t u_gid, v_gid;
auto& nbr_vec = ctx.complete_neighbor[v];
nbr_vec.reserve(degree);
std::vector<std::pair<vid_t, uint32_t>> msg_vec;
msg_vec.reserve(degree);

es = frag.GetOutgoingAdjList(v);
for (auto& e : es) {
auto u = e.get_neighbor();
if (ctx.global_degree[u] < ctx.global_degree[v]) {
std::pair<vid_t, uint32_t> msg;
msg.first = frag.Vertex2Gid(u);
typename FRAG_T::template vertex_array_t<uint32_t> is_rec;
is_rec.Init(vertices, 0);
auto es = frag.GetOutgoingAdjList(v);
for (auto& e : es) {
auto u = e.get_neighbor();
is_rec[u]++;
}
es = frag.GetIncomingAdjList(v);
for (auto& e : es) {
auto u = e.get_neighbor();
is_rec[u]++;
if (is_rec[u] == 2) {
msg.second = 2;
} else {
msg.second = 1;
ctx.rec_degree[v]++;
}
msg_vec.push_back(msg);
nbr_vec.push_back(std::make_pair(u, msg.second));
} else if (ctx.global_degree[u] == ctx.global_degree[v]) {
u_gid = frag.Vertex2Gid(u);
v_gid = frag.GetInnerVertexGid(v);
if (v_gid > u_gid) {
}

es = frag.GetOutgoingAdjList(v);
for (auto& e : es) {
auto u = e.get_neighbor();
if (ctx.global_degree[u] < ctx.global_degree[v]) {
std::pair<vid_t, uint32_t> msg;
msg.first = frag.Vertex2Gid(u);
if (is_rec[u] == 2) {
msg.second = 2;
} else {
msg.second = 1;
}
nbr_vec.push_back(std::make_pair(u, msg.second));
msg_vec.push_back(msg);
nbr_vec.push_back(std::make_pair(u, msg.second));
} else if (ctx.global_degree[u] == ctx.global_degree[v]) {
u_gid = frag.Vertex2Gid(u);
v_gid = frag.GetInnerVertexGid(v);
if (v_gid > u_gid) {
std::pair<vid_t, uint32_t> msg;
msg.first = frag.Vertex2Gid(u);
if (is_rec[u] == 2) {
msg.second = 2;
} else {
msg.second = 1;
}
nbr_vec.push_back(std::make_pair(u, msg.second));
msg_vec.push_back(msg);
}
}
}
}

es = frag.GetIncomingAdjList(v);
for (auto& e : es) {
auto u = e.get_neighbor();
if (ctx.global_degree[u] < ctx.global_degree[v]) {
std::pair<vid_t, uint32_t> msg;
msg.first = frag.Vertex2Gid(u);
if (is_rec[u] == 1) {
msg.second = 1;
msg_vec.push_back(msg);
nbr_vec.push_back(std::make_pair(u, 1));
}
} else if (ctx.global_degree[u] == ctx.global_degree[v]) {
u_gid = frag.Vertex2Gid(u);
v_gid = frag.GetInnerVertexGid(v);
if (v_gid > u_gid) {
es = frag.GetIncomingAdjList(v);
for (auto& e : es) {
auto u = e.get_neighbor();
if (ctx.global_degree[u] < ctx.global_degree[v]) {
std::pair<vid_t, uint32_t> msg;
msg.first = frag.Vertex2Gid(u);
if (is_rec[u] == 1) {
msg.second = 1;
msg_vec.push_back(msg);
nbr_vec.push_back(std::make_pair(u, 1));
}
} else if (ctx.global_degree[u] == ctx.global_degree[v]) {
u_gid = frag.Vertex2Gid(u);
v_gid = frag.GetInnerVertexGid(v);
if (v_gid > u_gid) {
std::pair<vid_t, uint32_t> msg;
msg.first = frag.Vertex2Gid(u);
if (is_rec[u] == 1) {
msg.second = 1;
msg_vec.push_back(msg);
nbr_vec.push_back(std::make_pair(u, 1));
}
}
}
}
}

messages.SendMsgThroughEdges<
fragment_t, std::vector<std::pair<vid_t, uint32_t>>>(
frag, v, msg_vec, tid);
messages.SendMsgThroughEdges<
fragment_t, std::vector<std::pair<vid_t, uint32_t>>>(
frag, v, msg_vec, tid);
}
});
messages.ForceContinue();
} else if (ctx.stage == 1) {
Expand All @@ -181,27 +185,42 @@ class Clustering
}
});

typename FRAG_T::template vertex_array_t<uint32_t> v0_nbr_set(vertices,
0);
for (auto v : inner_vertices) {
auto& v0_nbr_vec = ctx.complete_neighbor[v];
for (auto u : v0_nbr_vec) {
v0_nbr_set[u.first] = u.second;
}
for (auto u : v0_nbr_vec) {
auto& v1_nbr_vec = ctx.complete_neighbor[u.first];
for (auto w : v1_nbr_vec) {
if (v0_nbr_set[w.first] != 0) {
ctx.tricnt[u.first] += v0_nbr_set[w.first] * u.second * w.second;
ctx.tricnt[v] += v0_nbr_set[w.first] * u.second * w.second;
ctx.tricnt[w.first] += v0_nbr_set[w.first] * u.second * w.second;
std::vector<typename FRAG_T::template vertex_array_t<uint32_t>>
vertexsets(thread_num());
ForEach(
inner_vertices,
[&vertexsets, &frag](int tid) {
auto& ns = vertexsets[tid];
ns.Init(frag.Vertices(), 0);
},
[&vertexsets, &ctx](int tid, vertex_t v) {
if (ctx.global_degree[v] > 1) {
auto& v0_nbr_set = vertexsets[tid];
auto& v0_nbr_vec = ctx.complete_neighbor[v];
for (auto u : v0_nbr_vec) {
v0_nbr_set[u.first] = u.second;
}
for (auto u : v0_nbr_vec) {
auto& v1_nbr_vec = ctx.complete_neighbor[u.first];
for (auto w : v1_nbr_vec) {
if (v0_nbr_set[w.first] != 0) {
grape::atomic_add(
ctx.tricnt[u.first],
v0_nbr_set[w.first] * u.second * w.second);
grape::atomic_add(ctx.tricnt[v], v0_nbr_set[w.first] *
u.second * w.second);
grape::atomic_add(
ctx.tricnt[w.first],
v0_nbr_set[w.first] * u.second * w.second);
}
}
}
for (auto u : v0_nbr_vec) {
v0_nbr_set[u.first] = 0;
}
}
}
}
for (auto u : v0_nbr_vec) {
v0_nbr_set[u.first] = 0;
}
}
},
[](int tid) {});

ForEach(outer_vertices.begin(), outer_vertices.end(),
[&messages, &frag, &ctx](int tid, vertex_t v) {
Expand All @@ -215,7 +234,7 @@ class Clustering
ctx.stage = 3;
messages.ParallelProcess<fragment_t, int>(
thread_num(), frag, [&ctx](int tid, vertex_t u, int deg) {
grape::atomic_add(ctx.tricnt[u], deg);
grape::atomic_add(ctx.tricnt[u], static_cast<uint32_t>(deg));
});

// output result to context data
Expand All @@ -224,9 +243,13 @@ class Clustering
auto& tricnt = ctx.tricnt;
auto& ctx_data = ctx.data();
for (auto v : inner_vertices) {
int degree =
global_degree[v] * (global_degree[v] - 1) - 2 * rec_degree[v];
ctx_data[v] = degree == 0 ? 0.0 : 1.0 * tricnt[v] / degree;
if (global_degree[v] == 0 || global_degree[v] == 1) {
ctx_data[v] = 0;
} else {
int degree =
global_degree[v] * (global_degree[v] - 1) - 2 * rec_degree[v];
ctx_data[v] = degree == 0 ? 0.0 : 1.0 * tricnt[v] / degree;
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion analytical_engine/apps/clustering/clustering_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class ClusteringContext : public grape::VertexDataContext<FRAG_T, double> {
typename FRAG_T::template vertex_array_t<
std::vector<std::pair<vertex_t, uint32_t>>>
complete_neighbor;
typename FRAG_T::template vertex_array_t<int> tricnt;
typename FRAG_T::template vertex_array_t<uint32_t> tricnt;

int stage = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion python/graphscope/nx/utils/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def load_the_module(module_or_name):
try:
for name in names[1:]:
module_path = imp.find_module(name, [module_path[1]])
except ImportError:
except Exception:
return module_or_name
module = imp.load_module(module_or_name, *module_path)
return apply_networkx_patches(module)
Expand Down

0 comments on commit 65523c6

Please sign in to comment.