Skip to content

Commit

Permalink
Ktruss implementation (#4059)
Browse files Browse the repository at this point in the history
Implements SG and MG ktruss using graph primitives and drop `cuHornet`.

Closes #3447
Closes #3448 
Closes #3449 
Closes #3450 
Closes #3451
Closes #3452 
Closes #3453

Authors:
  - Joseph Nke (https://github.com/jnke2016)
  - Seunghwa Kang (https://github.com/seunghwak)

Approvers:
  - Brad Rees (https://github.com/BradReesWork)
  - Chuck Hastings (https://github.com/ChuckHastings)
  - Seunghwa Kang (https://github.com/seunghwak)
  - Rick Ratzel (https://github.com/rlratzel)

URL: #4059
  • Loading branch information
jnke2016 authored Mar 26, 2024
1 parent 8706115 commit f753e51
Show file tree
Hide file tree
Showing 15 changed files with 1,693 additions and 334 deletions.
32 changes: 3 additions & 29 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,6 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND
message(FATAL_ERROR "GCC compiler must be at least 9.3")
endif()

# Remove the following archs from CMAKE_CUDA_ARCHITECTURES that
# cuhornet currently doesn't support
#
# >= 90
set(supported_archs "70" "72" "75" "80" "86" "89" "90")
foreach( arch IN LISTS CMAKE_CUDA_ARCHITECTURES)
string(REPLACE "-real" "" arch ${arch})
if( arch IN_LIST supported_archs )
list(APPEND usable_arch_values ${arch})
endif()
endforeach()
# Make sure everything but the 'newest' arch
# is marked as `-real` so we only generate PTX for
# arch > 86
list(POP_BACK usable_arch_values latest_arch)
list(TRANSFORM usable_arch_values APPEND "-real")
if (usable_arch_values)
list(APPEND usable_arch_values ${latest_arch})
else()
list(APPEND usable_arch_values ${latest_arch}-real)
endif()

set(CMAKE_CUDA_ARCHITECTURES ${usable_arch_values})

# Write the version header
rapids_cmake_write_version_file(include/cugraph/version_config.hpp)
rapids_cmake_write_version_file(include/cugraph_c/version_config.hpp)
Expand Down Expand Up @@ -168,7 +144,6 @@ if(USE_CUGRAPH_OPS)
endif()

include(cmake/thirdparty/get_nccl.cmake)
include(cmake/thirdparty/get_cuhornet.cmake)

if (BUILD_CUGRAPH_MTMG_TESTS)
include(cmake/thirdparty/get_ucp.cmake)
Expand Down Expand Up @@ -197,6 +172,7 @@ set(CUGRAPH_SOURCES
src/community/detail/common_methods_sg.cu
src/community/detail/refine_sg.cu
src/community/detail/refine_mg.cu
src/community/edge_triangle_count_sg.cu
src/community/detail/maximal_independent_moves_sg.cu
src/community/detail/maximal_independent_moves_mg.cu
src/detail/utility_wrappers.cu
Expand All @@ -222,10 +198,10 @@ set(CUGRAPH_SOURCES
src/community/ecg_sg.cu
src/community/ecg_mg.cu
src/community/legacy/louvain.cu
src/community/legacy/ktruss.cu
src/community/legacy/ecg.cu
src/community/egonet_sg.cu
src/community/egonet_mg.cu
src/community/k_truss_sg.cu
src/sampling/random_walks.cu
src/sampling/random_walks_sg.cu
src/sampling/detail/prepare_next_frontier_sg.cu
Expand Down Expand Up @@ -391,7 +367,6 @@ if (USE_CUGRAPH_OPS)
$<$<BOOL:${CUDA_STATIC_RUNTIME}>:raft::raft>
$<$<BOOL:${CUDA_STATIC_RUNTIME}>:${COMPILED_RAFT_LIB}>
cuco::cuco
cugraph::cuHornet
NCCL::NCCL
)
else()
Expand All @@ -404,7 +379,6 @@ else()
$<$<BOOL:${CUDA_STATIC_RUNTIME}>:raft::raft>
$<$<BOOL:${CUDA_STATIC_RUNTIME}>:${COMPILED_RAFT_LIB}>
cuco::cuco
cugraph::cuHornet
NCCL::NCCL
)
endif()
Expand All @@ -427,6 +401,7 @@ add_library(cugraph_c
src/c_api/eigenvector_centrality.cpp
src/c_api/betweenness_centrality.cpp
src/c_api/core_number.cpp
src/c_api/k_truss.cpp
src/c_api/core_result.cpp
src/c_api/extract_ego.cpp
src/c_api/ecg.cpp
Expand Down Expand Up @@ -455,7 +430,6 @@ add_library(cugraph_c
src/c_api/weakly_connected_components.cpp
src/c_api/strongly_connected_components.cpp
src/c_api/allgather.cpp
src/c_api/legacy_k_truss.cpp
)
add_library(cugraph::cugraph_c ALIAS cugraph_c)

Expand Down
45 changes: 0 additions & 45 deletions cpp/cmake/thirdparty/get_cuhornet.cmake

This file was deleted.

73 changes: 32 additions & 41 deletions cpp/include/cugraph/algorithms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,41 +427,6 @@ void connected_components(legacy::GraphCSRView<VT, ET, WT> const& graph,
cugraph_cc_t connectivity_type,
VT* labels);

/**
* @brief Compute k truss for a graph ** temporary
*
* K Truss is the maximal subgraph of a graph which contains at least three
* vertices where every edge is incident to at least k-2 triangles.
*
* This version is a temporary solution to clean up python integration through the C API.
*
* This version is only supported SG.
*
* @throws cugraph::logic_error with a custom message when an error
* occurs.
*
* @tparam vertex_t Type of vertex identifiers. Supported value : int (signed, 32-bit)
* @tparam weight_t Type of edge weights. Supported values : float or double.
*
* @param[in] handle Library handle (RAFT).
* @param[in] src Source vertices from COO
* @param[in] dst Destination vertices from COO
* @param[in] wgt Optional edge weights from COO
* @param[in] k The order of the truss
* @return Tuple containing extracted src, dst and optional weights for the
* subgraph
*/
template <typename vertex_t, typename weight_t>
std::tuple<rmm::device_uvector<vertex_t>,
rmm::device_uvector<vertex_t>,
std::optional<rmm::device_uvector<weight_t>>>
k_truss_subgraph(raft::handle_t const& handle,
raft::device_span<vertex_t> src,
raft::device_span<vertex_t> dst,
std::optional<raft::device_span<weight_t>> wgt,
size_t number_of_vertices,
int k);

/**
* @brief Compute Hungarian algorithm on a weighted bipartite graph
*
Expand Down Expand Up @@ -1842,7 +1807,7 @@ void weakly_connected_components(raft::handle_t const& handle,
enum class k_core_degree_type_t { IN = 0, OUT = 1, INOUT = 2 };

/**
* @brief Compute core numbers of individual vertices from K-core decomposition.
* @brief Compute core numbers of individual vertices from K-Core decomposition.
*
* The input graph should not have self-loops nor multi-edges. Currently, only undirected graphs are
* supported.
Expand All @@ -1855,11 +1820,11 @@ enum class k_core_degree_type_t { IN = 0, OUT = 1, INOUT = 2 };
* handles to various CUDA libraries) to run graph algorithms.
* @param graph_view Graph view object.
* @param core_numbers Pointer to the output core number array.
* @param degree_type Dictate whether to compute the K-core decomposition based on in-degrees,
* @param degree_type Dictate whether to compute the K-Core decomposition based on in-degrees,
* out-degrees, or in-degrees + out_degrees.
* @param k_first Find K-cores from K = k_first. Any vertices that do not belong to k_first-core
* @param k_first Find K-Cores from K = k_first. Any vertices that do not belong to k_first-core
* will have core numbers of 0.
* @param k_last Find K-cores to K = k_last. Any vertices that belong to (k_last)-core will have
* @param k_last Find K-Cores to K = k_last. Any vertices that belong to (k_last)-core will have
* their core numbers set to their degrees on k_last-core.
* @param do_expensive_check A flag to run expensive checks for input arguments (if set to `true`).
*/
Expand All @@ -1873,7 +1838,7 @@ void core_number(raft::handle_t const& handle,
bool do_expensive_check = false);

/**
* @brief Extract K Core of a graph
* @brief Extract K-Core of a graph
*
* @throws cugraph::logic_error when an error occurs.
*
Expand All @@ -1884,7 +1849,7 @@ void core_number(raft::handle_t const& handle,
* @param graph_view Graph view object.
* @param edge_weight_view Optional view object holding edge weights for @p graph_view.
* @param k Order of the core. This value must not be negative.
* @param degree_type Optional parameter to dictate whether to compute the K-core decomposition
* @param degree_type Optional parameter to dictate whether to compute the K-Core decomposition
* based on in-degrees, out-degrees, or in-degrees + out_degrees. One of @p
* degree_type and @p core_numbers must be specified.
* @param core_numbers Optional output from core_number algorithm. If not specified then
Expand Down Expand Up @@ -2040,6 +2005,32 @@ void triangle_count(raft::handle_t const& handle,
raft::device_span<edge_t> counts,
bool do_expensive_check = false);

/*
* @brief Compute K-Truss.
*
* Extract the K-Truss subgraph of a graph
*
* @tparam vertex_t Type of vertex identifiers. Needs to be an integral type.
* @tparam edge_t Type of edge identifiers. Needs to be an integral type.
* @tparam multi_gpu Flag indicating whether template instantiation should target single-GPU (false)
* @param handle RAFT handle object to encapsulate resources (e.g. CUDA stream, communicator, and
* handles to various CUDA libraries) to run graph algorithms.
* @param graph_view Graph view object.
* @param edge_weight_view Optional view object holding edge weights for @p graph_view.
* @param k The desired k to be used for extracting the K-Truss subgraph
* @param do_expensive_check A flag to run expensive checks for input arguments (if set to `true`).
* @return edge list of the K-Truss subgraph
*/
template <typename vertex_t, typename edge_t, typename weight_t, bool multi_gpu>
std::tuple<rmm::device_uvector<vertex_t>,
rmm::device_uvector<vertex_t>,
std::optional<rmm::device_uvector<weight_t>>>
k_truss(raft::handle_t const& handle,
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,
edge_t k,
bool do_expensive_check = false);

/**
* @brief Compute Jaccard similarity coefficient
*
Expand Down
6 changes: 3 additions & 3 deletions cpp/include/cugraph/utilities/graph_traits.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2023, NVIDIA CORPORATION.
* Copyright (c) 2021-2024, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -67,8 +67,8 @@ struct is_candidate {
};

// meta-function that constrains
// all 3 template param candidates where vertex_t and edge_t
// are restricted to int32_t:
// vertex_t and edge_t are restricted to int32_t:
// FIXME: Drop this functor as it was only used by legacy K-Truss
//
template <typename vertex_t, typename edge_t, typename weight_t>
struct is_candidate_legacy {
Expand Down
34 changes: 11 additions & 23 deletions cpp/src/c_api/legacy_k_truss.cpp → cpp/src/c_api/k_truss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct k_truss_functor : public cugraph::c_api::abstract_functor {
bool multi_gpu>
void operator()()
{
if constexpr (!cugraph::is_candidate_legacy<vertex_t, edge_t, weight_t>::value) {
if constexpr (!cugraph::is_candidate<vertex_t, edge_t, weight_t>::value) {
unsupported();
} else if constexpr (multi_gpu) {
unsupported();
Expand All @@ -81,26 +81,14 @@ struct k_truss_functor : public cugraph::c_api::abstract_functor {
auto number_map = reinterpret_cast<rmm::device_uvector<vertex_t>*>(graph_->number_map_);

auto graph_view = graph->view();
rmm::device_uvector<vertex_t> src(0, handle_.get_stream());
rmm::device_uvector<vertex_t> dst(0, handle_.get_stream());
std::optional<rmm::device_uvector<weight_t>> wgt{std::nullopt};

std::tie(src, dst, wgt, std::ignore) = cugraph::decompress_to_edgelist(
handle_,
graph_view,
edge_weights ? std::make_optional(edge_weights->view()) : std::nullopt,
std::optional<cugraph::edge_property_view_t<edge_t, edge_t const*>>{std::nullopt},
std::optional<raft::device_span<vertex_t const>>(std::nullopt),
do_expensive_check_);

auto [result_src, result_dst, result_wgt] = cugraph::k_truss_subgraph(
handle_,
raft::device_span<vertex_t>(src.data(), src.size()),
raft::device_span<vertex_t>(dst.data(), dst.size()),
wgt ? std::make_optional(raft::device_span<weight_t>(wgt->data(), wgt->size()))
: std::nullopt,
graph_view.number_of_vertices(),
k_);
auto [result_src, result_dst, result_wgt] =
cugraph::k_truss<vertex_t, edge_t, weight_t, multi_gpu>(
handle_,
graph_view,
edge_weights ? std::make_optional(edge_weights->view()) : std::nullopt,
k_,
do_expensive_check_);

cugraph::unrenumber_int_vertices<vertex_t, multi_gpu>(
handle_,
Expand All @@ -127,9 +115,9 @@ struct k_truss_functor : public cugraph::c_api::abstract_functor {
result_ = new cugraph::c_api::cugraph_induced_subgraph_result_t{
new cugraph::c_api::cugraph_type_erased_device_array_t(result_src, graph_->vertex_type_),
new cugraph::c_api::cugraph_type_erased_device_array_t(result_dst, graph_->vertex_type_),
wgt ? new cugraph::c_api::cugraph_type_erased_device_array_t(*result_wgt,
graph_->weight_type_)
: NULL,
result_wgt ? new cugraph::c_api::cugraph_type_erased_device_array_t(*result_wgt,
graph_->weight_type_)
: NULL,
NULL,
NULL,
new cugraph::c_api::cugraph_type_erased_device_array_t(edge_offsets,
Expand Down
Loading

0 comments on commit f753e51

Please sign in to comment.