Skip to content

Commit

Permalink
Fix Leiden refinement phase
Browse files Browse the repository at this point in the history
  • Loading branch information
Naim committed Nov 8, 2023
1 parent ac5b981 commit a21509f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 7 deletions.
36 changes: 36 additions & 0 deletions cpp/src/community/detail/common_methods.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,27 @@ struct reduce_op_t {
}
};

// a workaround for cudaErrorInvalidDeviceFunction error when device lambda is used
template <typename vertex_t, typename weight_t>
struct count_updown_moves_op_t {
bool up_down{};
__device__ auto operator()(thrust::tuple<vertex_t, thrust::tuple<vertex_t, weight_t>> p) const
{
vertex_t old_cluster = thrust::get<0>(p);
auto new_cluster_gain_pair = thrust::get<1>(p);
vertex_t new_cluster = thrust::get<0>(new_cluster_gain_pair);
weight_t delta_modularity = thrust::get<1>(new_cluster_gain_pair);

auto result_assignment =
(delta_modularity > weight_t{0})
? (((new_cluster > old_cluster) != up_down) ? old_cluster : new_cluster)
: old_cluster;

return (delta_modularity > weight_t{0})
? (((new_cluster > old_cluster) != up_down) ? false : true)
: false;
}
};
// a workaround for cudaErrorInvalidDeviceFunction error when device lambda is used
template <typename vertex_t, typename weight_t>
struct cluster_update_op_t {
Expand Down Expand Up @@ -394,6 +415,21 @@ rmm::device_uvector<vertex_t> update_clustering_by_delta_modularity(
detail::reduce_op_t<vertex_t, weight_t>{},
cugraph::get_dataframe_buffer_begin(output_buffer));

int nr_moves = thrust::count_if(
handle.get_thrust_policy(),
thrust::make_zip_iterator(thrust::make_tuple(
next_clusters_v.begin(), cugraph::get_dataframe_buffer_begin(output_buffer))),
thrust::make_zip_iterator(
thrust::make_tuple(next_clusters_v.end(), cugraph::get_dataframe_buffer_end(output_buffer))),
detail::count_updown_moves_op_t<vertex_t, weight_t>{up_down});

if (multi_gpu) {
nr_moves = host_scalar_allreduce(
handle.get_comms(), nr_moves, raft::comms::op_t::SUM, handle.get_stream());
}

if (nr_moves == 0) { up_down = !up_down; }

thrust::transform(handle.get_thrust_policy(),
next_clusters_v.begin(),
next_clusters_v.end(),
Expand Down
18 changes: 11 additions & 7 deletions cpp/src/community/detail/refine_impl.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ struct leiden_key_aggregated_edge_op_t {

// E(Cr, S-Cr) > ||Cr||*(||S|| -||Cr||)
bool is_dst_leiden_cluster_well_connected =
dst_leiden_cut_to_louvain >
resolution * dst_leiden_volume * (louvain_cluster_volume - dst_leiden_volume);
dst_leiden_cut_to_louvain > resolution * dst_leiden_volume *
(louvain_cluster_volume - dst_leiden_volume) /
total_edge_weight;

// E(v, Cr-v) - ||v||* ||Cr-v||/||V(G)||
// aggregated_weight_to_neighboring_leiden_cluster == E(v, Cr-v)?
Expand All @@ -100,9 +101,9 @@ struct leiden_key_aggregated_edge_op_t {
if ((louvain_of_dst_leiden_cluster == src_louvain_cluster) &&
is_dst_leiden_cluster_well_connected) {
mod_gain = aggregated_weight_to_neighboring_leiden_cluster -
resolution * src_weighted_deg * (dst_leiden_volume - src_weighted_deg) /
total_edge_weight;

resolution * src_weighted_deg * dst_leiden_volume / total_edge_weight;
// NOTE: Disable random moves in refinement phase for now.
#if 0
weight_t random_number{0.0};
if (mod_gain > 0.0) {
auto flat_id = uint64_t{threadIdx.x + blockIdx.x * blockDim.x};
Expand All @@ -117,6 +118,8 @@ struct leiden_key_aggregated_edge_op_t {
? __expf(static_cast<float>((2.0 * mod_gain) / (theta * total_edge_weight))) *
random_number
: -1.0;
#endif
mod_gain = mod_gain > 0.0 ? mod_gain : -1.0;
}
}

Expand Down Expand Up @@ -240,11 +243,12 @@ refine_clustering(
wcut_deg_and_cluster_vol_triple_begin,
wcut_deg_and_cluster_vol_triple_end,
singleton_and_connected_flags.begin(),
[resolution] __device__(auto wcut_wdeg_and_louvain_volume) {
[resolution, total_edge_weight] __device__(auto wcut_wdeg_and_louvain_volume) {
auto wcut = thrust::get<0>(wcut_wdeg_and_louvain_volume);
auto wdeg = thrust::get<1>(wcut_wdeg_and_louvain_volume);
auto louvain_volume = thrust::get<2>(wcut_wdeg_and_louvain_volume);
return wcut > (resolution * wdeg * (louvain_volume - wdeg));
return wcut >
(resolution * wdeg * (louvain_volume - wdeg) / total_edge_weight);
});

edge_src_property_t<GraphViewType, weight_t> src_louvain_cluster_weight_cache(handle);
Expand Down

0 comments on commit a21509f

Please sign in to comment.