Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ set(CUGRAPH_SG_SOURCES
src/community/detail/common_methods_sg_v32_e32.cu
src/community/detail/refine_sg_v64_e64.cu
src/community/detail/refine_sg_v32_e32.cu
src/community/detail/decision_graph_mis_sg_v64_e64.cu
src/community/detail/decision_graph_mis_sg_v32_e32.cu
src/community/edge_triangle_count_sg_v64_e64.cu
src/community/edge_triangle_count_sg_v32_e32.cu
src/community/detail/maximal_independent_moves_sg_v64_e64.cu
Expand Down Expand Up @@ -348,6 +350,8 @@ set(CUGRAPH_MG_SOURCES
src/community/detail/common_methods_mg_v32_e32.cu
src/community/detail/refine_mg_v64_e64.cu
src/community/detail/refine_mg_v32_e32.cu
src/community/detail/decision_graph_mis_mg_v64_e64.cu
src/community/detail/decision_graph_mis_mg_v32_e32.cu
src/community/edge_triangle_count_mg_v64_e64.cu
src/community/edge_triangle_count_mg_v32_e32.cu
src/community/detail/maximal_independent_moves_mg_v64_e64.cu
Expand Down Expand Up @@ -486,6 +490,7 @@ foreach(suffix IN LISTS cugraph_suffixes)
CUDA_STANDARD_REQUIRED ON
POSITION_INDEPENDENT_CODE ON
INTERFACE_POSITION_INDEPENDENT_CODE ON
NO_CUDART_DEP ON
)

################################################################################
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/community/detail/common_methods.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ rmm::device_uvector<vertex_t> update_clustering_by_delta_modularity(
cugraph::get_dataframe_buffer_end(output_buffer)),
detail::count_updown_moves_op_t<vertex_t, weight_t>{up_down});

if (multi_gpu) {
if constexpr (multi_gpu) {
nr_moves = host_scalar_allreduce(
handle.get_comms(), nr_moves, raft::comms::op_t::SUM, handle.get_stream());
}
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/community/detail/common_methods.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
Expand Down Expand Up @@ -51,7 +51,7 @@ void timer_display_and_clear(raft::handle_t const& handle,
HighResTimer const& hr_timer,
std::ostream& os)
{
if (multi_gpu) {
if constexpr (multi_gpu) {
if (handle.get_comms().get_rank() == 0) hr_timer.display_and_clear(os);
} else {
hr_timer.display_and_clear(os);
Expand Down
97 changes: 97 additions & 0 deletions cpp/src/community/detail/decision_graph_mis.cuh
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include "common_methods.hpp"
#include "decision_graph_mis.hpp"
#include "maximal_independent_moves.cuh"

#include <cugraph/arithmetic_variant_types.hpp>
#include <cugraph/detail/utility_wrappers.hpp>
#include <cugraph/graph.hpp>
#include <cugraph/graph_functions.hpp>
#include <cugraph/shuffle_functions.hpp>

#include <optional>
#include <tuple>

namespace cugraph {
namespace detail {

template <typename vertex_t, bool multi_gpu>
rmm::device_uvector<vertex_t> vertices_in_mis_from_decision_edgelist(
raft::handle_t const& handle,
raft::random::RngState& rng_state,
raft::host_span<vertex_t const> vertex_partition_range_lasts,
rmm::device_uvector<vertex_t>&& d_srcs,
rmm::device_uvector<vertex_t>&& d_dsts)
{
// NOTE: the maximum number of edges is the number of vertices in the graph,
// so we can use the vertex type for the edge type
using edge_t = vertex_t;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we better avoid this?

We currently don't build for edge_t != vertex_t cases in our regular release but we still allow users to manually build for these cases.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is there a guarantee that # edges <= # vertices in this use case? In that case, we should add a comment here to avoid future confusion.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I've added a comment. The number of entries in d_srcs/d_dsts starts as the number of vertices in the graph and then gets filtered down, so it's guaranteed to fit in a vertex_t.


constexpr bool decision_store_transposed = false;

cugraph::graph_t<vertex_t, edge_t, decision_store_transposed, multi_gpu> decision_graph(handle);

if constexpr (multi_gpu) {
std::tie(d_srcs, d_dsts, std::ignore) =
cugraph::shuffle_ext_edges(handle,
std::move(d_srcs),
std::move(d_dsts),
std::vector<arithmetic_device_uvector_t>{},
false);
}

std::optional<rmm::device_uvector<vertex_t>> renumber_map{std::nullopt};
std::tie(decision_graph, std::ignore, renumber_map) =
create_graph_from_edgelist<vertex_t, edge_t, decision_store_transposed, multi_gpu>(
handle,
std::nullopt,
std::move(d_srcs),
std::move(d_dsts),
std::vector<arithmetic_device_uvector_t>{},
cugraph::graph_properties_t{false, false},
true /* renumber */);

auto decision_graph_view = decision_graph.view();

auto vertices_in_mis =
maximal_independent_moves<vertex_t, edge_t, multi_gpu>(handle, decision_graph_view, rng_state);

rmm::device_uvector<vertex_t> numbering_indices((*renumber_map).size(), handle.get_stream());
detail::sequence_fill(handle.get_stream(),
numbering_indices.data(),
numbering_indices.size(),
decision_graph_view.local_vertex_partition_range_first());

relabel<vertex_t, multi_gpu>(
handle,
std::make_tuple(static_cast<vertex_t const*>(numbering_indices.begin()),
static_cast<vertex_t const*>((*renumber_map).begin())),
decision_graph_view.local_vertex_partition_range_size(),
vertices_in_mis.data(),
vertices_in_mis.size(),
false);

numbering_indices.resize(0, handle.get_stream());
numbering_indices.shrink_to_fit(handle.get_stream());

(*renumber_map).resize(0, handle.get_stream());
(*renumber_map).shrink_to_fit(handle.get_stream());

if constexpr (multi_gpu) {
std::tie(vertices_in_mis, std::ignore) =
cugraph::shuffle_int_vertices(handle,
std::move(vertices_in_mis),
std::vector<cugraph::arithmetic_device_uvector_t>{},
vertex_partition_range_lasts);
}

return vertices_in_mis;
}

} // namespace detail
} // namespace cugraph
31 changes: 31 additions & 0 deletions cpp/src/community/detail/decision_graph_mis.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include <raft/core/handle.hpp>
#include <raft/core/host_span.hpp>
#include <raft/random/rng_state.hpp>

#include <rmm/device_uvector.hpp>

namespace cugraph {
namespace detail {

/**
* @brief Build a decision graph from an edgelist, compute a maximal independent set of moves,
* relabel MIS vertices to original ids, and (multi-GPU) shuffle them to owning ranks.
*
* @param vertex_partition_range_lasts Used only when multi_gpu is true (shuffle_int_vertices).
*/
template <typename vertex_t, bool multi_gpu>
rmm::device_uvector<vertex_t> vertices_in_mis_from_decision_edgelist(
raft::handle_t const& handle,
raft::random::RngState& rng_state,
raft::host_span<vertex_t const> vertex_partition_range_lasts,
rmm::device_uvector<vertex_t>&& d_srcs,
rmm::device_uvector<vertex_t>&& d_dsts);

} // namespace detail
} // namespace cugraph
18 changes: 18 additions & 0 deletions cpp/src/community/detail/decision_graph_mis_mg_v32_e32.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#include "decision_graph_mis.cuh"

namespace cugraph {
namespace detail {

template rmm::device_uvector<int32_t> vertices_in_mis_from_decision_edgelist<int32_t, true>(
raft::handle_t const& handle,
raft::random::RngState& rng_state,
raft::host_span<int32_t const> vertex_partition_range_lasts,
rmm::device_uvector<int32_t>&& d_srcs,
rmm::device_uvector<int32_t>&& d_dsts);

} // namespace detail
} // namespace cugraph
18 changes: 18 additions & 0 deletions cpp/src/community/detail/decision_graph_mis_mg_v64_e64.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#include "decision_graph_mis.cuh"

namespace cugraph {
namespace detail {

template rmm::device_uvector<int64_t> vertices_in_mis_from_decision_edgelist<int64_t, true>(
raft::handle_t const& handle,
raft::random::RngState& rng_state,
raft::host_span<int64_t const> vertex_partition_range_lasts,
rmm::device_uvector<int64_t>&& d_srcs,
rmm::device_uvector<int64_t>&& d_dsts);

} // namespace detail
} // namespace cugraph
18 changes: 18 additions & 0 deletions cpp/src/community/detail/decision_graph_mis_sg_v32_e32.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#include "decision_graph_mis.cuh"

namespace cugraph {
namespace detail {

template rmm::device_uvector<int32_t> vertices_in_mis_from_decision_edgelist<int32_t, false>(
raft::handle_t const& handle,
raft::random::RngState& rng_state,
raft::host_span<int32_t const> vertex_partition_range_lasts,
rmm::device_uvector<int32_t>&& d_srcs,
rmm::device_uvector<int32_t>&& d_dsts);

} // namespace detail
} // namespace cugraph
18 changes: 18 additions & 0 deletions cpp/src/community/detail/decision_graph_mis_sg_v64_e64.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#include "decision_graph_mis.cuh"

namespace cugraph {
namespace detail {

template rmm::device_uvector<int64_t> vertices_in_mis_from_decision_edgelist<int64_t, false>(
raft::handle_t const& handle,
raft::random::RngState& rng_state,
raft::host_span<int64_t const> vertex_partition_range_lasts,
rmm::device_uvector<int64_t>&& d_srcs,
rmm::device_uvector<int64_t>&& d_dsts);

} // namespace detail
} // namespace cugraph
4 changes: 2 additions & 2 deletions cpp/src/community/detail/maximal_independent_moves.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ rmm::device_uvector<vertex_t> maximal_independent_moves(
// Select a random set of candidate vertices

vertex_t nr_remaining_vertices_to_check = remaining_vertices.size();
if (multi_gpu) {
if constexpr (multi_gpu) {
nr_remaining_vertices_to_check = host_scalar_allreduce(handle.get_comms(),
nr_remaining_vertices_to_check,
raft::comms::op_t::SUM,
Expand Down Expand Up @@ -268,7 +268,7 @@ rmm::device_uvector<vertex_t> maximal_independent_moves(
remaining_vertices.begin());

nr_remaining_vertices_to_check = remaining_vertices.size();
if (multi_gpu) {
if constexpr (multi_gpu) {
nr_remaining_vertices_to_check = host_scalar_allreduce(handle.get_comms(),
nr_remaining_vertices_to_check,
raft::comms::op_t::SUM,
Expand Down
41 changes: 18 additions & 23 deletions cpp/src/community/detail/refine.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION.
* SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION.
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
Expand All @@ -16,28 +16,23 @@
namespace cugraph {
namespace detail {

template <typename graph_view_t, typename weight_t>
std::tuple<rmm::device_uvector<typename graph_view_t::vertex_type>,
std::pair<rmm::device_uvector<typename graph_view_t::vertex_type>,
rmm::device_uvector<typename graph_view_t::vertex_type>>>
refine_clustering(
raft::handle_t const& handle,
raft::random::RngState& rng_state,
graph_view_t const& graph_view,
std::optional<edge_property_view_t<typename graph_view_t::edge_type, weight_t const*>>
edge_weight_view,
weight_t total_edge_weight,
weight_t resolution,
weight_t theta,
rmm::device_uvector<weight_t> const& vertex_weights_v,
rmm::device_uvector<typename graph_view_t::vertex_type>&& cluster_keys_v,
rmm::device_uvector<weight_t>&& cluster_weights_v,
rmm::device_uvector<typename graph_view_t::vertex_type>&& next_clusters_v,
edge_src_property_t<typename graph_view_t::vertex_type, weight_t> const& src_vertex_weights_cache,
edge_src_property_t<typename graph_view_t::vertex_type, typename graph_view_t::vertex_type> const&
src_clusters_cache,
edge_dst_property_t<typename graph_view_t::vertex_type, typename graph_view_t::vertex_type> const&
dst_clusters_cache);
template <typename vertex_t, typename edge_t, bool multi_gpu, typename weight_t>
std::tuple<rmm::device_uvector<vertex_t>,
std::pair<rmm::device_uvector<vertex_t>, rmm::device_uvector<vertex_t>>>
refine_clustering(raft::handle_t const& handle,
raft::random::RngState& rng_state,
graph_view_t<vertex_t, edge_t, false, multi_gpu> const& graph_view,
std::optional<edge_property_view_t<edge_t, weight_t const*>> edge_weight_view,
weight_t total_edge_weight,
weight_t resolution,
weight_t theta,
rmm::device_uvector<weight_t> const& vertex_weights_v,
rmm::device_uvector<vertex_t>&& cluster_keys_v,
rmm::device_uvector<weight_t>&& cluster_weights_v,
rmm::device_uvector<vertex_t>&& next_clusters_v,
edge_src_property_t<vertex_t, weight_t> const& src_vertex_weights_cache,
edge_src_property_t<vertex_t, vertex_t> const& src_clusters_cache,
edge_dst_property_t<vertex_t, vertex_t> const& dst_clusters_cache);

}
} // namespace cugraph
Loading
Loading