Skip to content

Commit

Permalink
HITS C API implementation (#2150)
Browse files Browse the repository at this point in the history
Closes #2092 

Provide the C API implementation for HITS.  Adds a unit tester for MG, updates the unit tests for both SG and MG.

Authors:
  - Chuck Hastings (https://github.com/ChuckHastings)

Approvers:
  - Brad Rees (https://github.com/BradReesWork)
  - Seunghwa Kang (https://github.com/seunghwak)

URL: #2150
  • Loading branch information
ChuckHastings authored Mar 29, 2022
1 parent ad770d2 commit 87be0b3
Show file tree
Hide file tree
Showing 24 changed files with 1,073 additions and 70 deletions.
34 changes: 34 additions & 0 deletions cpp/include/cugraph/detail/shuffle_wrappers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,39 @@ rmm::device_uvector<size_t> groupby_and_count_edgelist_by_local_partition_id(
std::optional<rmm::device_uvector<weight_t>>& d_edgelist_weights,
bool groupby_and_count_local_partition_by_minor = false);

/**
* @brief Collect vertex values (represented as k/v pairs across cluster) and return
* local value arrays on the GPU responsible for each vertex.
*
* Data will be shuffled, renumbered and initialized with the default value,
* then: return_array[d_vertices[i]] = d_values[i]
*
* @tparam vertex_t Type of vertex identifiers. Needs to be an integral type.
* @tparam value_t Type of value associated with the vertex.
* @tparam bool multi_gpu flag
*
* @param[in] handle RAFT handle object to encapsulate resources (e.g. CUDA stream, communicator,
* and handles to various CUDA libraries) to run graph algorithms.
* @param[in] d_vertices Vertex IDs for the k/v pair
* @param[in] d_values Values for the k/v pair
* @param[in] The number map for performing renumbering
* @param[in] local_vertex_first The first vertex id assigned to the local GPU
* @param[in] local_vertex_last The last vertex id assigned to the local GPU
* @param[in] default_value The default value the return array will be initialized by
* @param[in] do_expensive_check If true, enable expensive validation checks
* @return device vector of values, where return[i] is the value associated with
* vertex (i + local_vertex_first)
*/
template <typename vertex_t, typename value_t, bool multi_gpu>
rmm::device_uvector<value_t> collect_local_vertex_values_from_ext_vertex_value_pairs(
raft::handle_t const& handle,
rmm::device_uvector<vertex_t>&& d_vertices,
rmm::device_uvector<value_t>&& d_values,
rmm::device_uvector<vertex_t> const& number_map,
vertex_t local_vertex_first,
vertex_t local_vertex_last,
value_t default_value,
bool do_expensive_check);

} // namespace detail
} // namespace cugraph
33 changes: 32 additions & 1 deletion cpp/include/cugraph/graph_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ renumber_edgelist(raft::handle_t const& handle,
bool do_expensive_check = false);

/**
* @brief Renumber external vertices to internal vertices based on the provoided @p
* @brief Renumber external vertices to internal vertices based on the provided @p
* renumber_map_labels.
*
* Note cugraph::invalid_id<vertex_t>::value remains unchanged.
Expand Down Expand Up @@ -302,6 +302,37 @@ std::enable_if_t<!multi_gpu, void> unrenumber_local_int_edges(raft::handle_t con
vertex_t num_vertices,
bool do_expensive_check = false);

/**
* @brief Renumber local external vertices to internal vertices based on the provided @p
* renumber_map_labels.
*
* Note cugraph::invalid_id<vertex_t>::value remains unchanged.
*
* @tparam vertex_t Type of vertex identifiers. Needs to be an integral type.
* @tparam multi_gpu Flag indicating whether template instantiation should target single-GPU (false)
* or multi-GPU (true).
* @param handle RAFT handle object to encapsulate resources (e.g. CUDA stream, communicator, and
* handles to various CUDA libraries) to run graph algorithms.
* @param vertices Pointer to the vertices to be renumbered. The input external vertices are
* renumbered to internal vertices in-place.
* @param num_vertices Number of vertices to be renumbered.
* @param renumber_map_labels Pointer to the external vertices corresponding to the internal
* vertices in the range [@p local_int_vertex_first, @p local_int_vertex_last).
* @param local_int_vertex_first The first local internal vertex (inclusive, assigned to this
* process in multi-GPU).
* @param local_int_vertex_last The last local internal vertex (exclusive, assigned to this process
* in multi-GPU).
* @param do_expensive_check A flag to run expensive checks for input arguments (if set to `true`).
*/
template <typename vertex_t, bool multi_gpu>
void renumber_local_ext_vertices(raft::handle_t const& handle,
vertex_t* vertices /* [INOUT] */,
size_t num_vertices,
vertex_t const* renumber_map_labels,
vertex_t local_int_vertex_first,
vertex_t local_int_vertex_last,
bool do_expensive_check = false);

/**
* @brief Symmetrize edgelist.
*
Expand Down
4 changes: 2 additions & 2 deletions cpp/include/cugraph_c/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef struct {
bool_t is_multigraph;
} cugraph_graph_properties_t;

// FIXME: Add support for specifying isloated vertices
// FIXME: Add support for specifying isolated vertices
/**
* @brief Construct an SG graph
*
Expand Down Expand Up @@ -74,7 +74,7 @@ cugraph_error_code_t cugraph_sg_graph_create(const cugraph_resource_handle_t* ha
// but didn't want to confuse with original cugraph_free_graph
void cugraph_sg_graph_free(cugraph_graph_t* graph);

// FIXME: Add support for specifying isloated vertices
// FIXME: Add support for specifying isolated vertices
/**
* @brief Construct an MG graph
*
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/c_api/bfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ struct bfs_functor : public abstract_functor {

auto number_map = reinterpret_cast<rmm::device_uvector<vertex_t>*>(graph_->number_map_);

rmm::device_uvector<vertex_t> vertex_ids(graph->get_number_of_vertices(),
handle_.get_stream());
rmm::device_uvector<vertex_t> distances(graph->get_number_of_vertices(),
handle_.get_stream());
rmm::device_uvector<vertex_t> predecessors(0, handle_.get_stream());
Expand Down Expand Up @@ -116,6 +114,8 @@ struct bfs_functor : public abstract_functor {
static_cast<vertex_t>(depth_limit_),
do_expensive_check_);

rmm::device_uvector<vertex_t> vertex_ids(graph->get_number_of_vertices(),
handle_.get_stream());
raft::copy(vertex_ids.data(), number_map->data(), vertex_ids.size(), handle_.get_stream());

if (compute_predecessors_) {
Expand Down
69 changes: 38 additions & 31 deletions cpp/src/c_api/hits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <c_api/utils.hpp>

#include <cugraph/algorithms.hpp>
#include <cugraph/detail/shuffle_wrappers.hpp>
#include <cugraph/detail/utility_wrappers.hpp>
#include <cugraph/graph_functions.hpp>

Expand Down Expand Up @@ -104,49 +105,55 @@ struct hits_functor : public cugraph::c_api::abstract_functor {

auto number_map = reinterpret_cast<rmm::device_uvector<vertex_t>*>(graph_->number_map_);

rmm::device_uvector<vertex_t> vertex_ids(graph_view.get_number_of_local_vertices(),
handle_.get_stream());
rmm::device_uvector<weight_t> hubs(graph_view.get_number_of_local_vertices(),
handle_.get_stream());
rmm::device_uvector<weight_t> authorities(graph_view.get_number_of_local_vertices(),
handle_.get_stream());
weight_t hub_score_differences{0};
size_t number_of_iterations{0};

#if 0
// FIXME: Implementation will look something like this.

if (initial_hubs_guess_ != nullptr) {
//
// Need to renumber initial_hubs_guess_vertices
// Need to shuffle and populate hubs
//
// This is the original pagerank code, it will be sort of like this
renumber_ext_vertices<vertex_t, multi_gpu>(handle_,
personalization_vertices_->as_type<vertex_t>(),
personalization_vertices_->size_,
number_map->data(),
graph_view.get_local_vertex_first(),
graph_view.get_local_vertex_last(),
do_expensive_check_);
if (initial_hubs_guess_vertices_ != nullptr) {
rmm::device_uvector<vertex_t> guess_vertices(initial_hubs_guess_vertices_->size_,
handle_.get_stream());
rmm::device_uvector<weight_t> guess_values(initial_hubs_guess_values_->size_,
handle_.get_stream());

raft::copy(guess_vertices.data(),
initial_hubs_guess_vertices_->as_type<vertex_t>(),
guess_vertices.size(),
handle_.get_stream());
raft::copy(guess_values.data(),
initial_hubs_guess_values_->as_type<weight_t>(),
guess_values.size(),
handle_.get_stream());

hubs = cugraph::detail::
collect_local_vertex_values_from_ext_vertex_value_pairs<vertex_t, weight_t, multi_gpu>(
handle_,
std::move(guess_vertices),
std::move(guess_values),
*number_map,
graph_view.get_local_vertex_first(),
graph_view.get_local_vertex_last(),
weight_t{0},
do_expensive_check_);
}

// TODO: Add these to the result
std::tie(hub_score_differences, number_of_iterations) =
cugraph::hits<vertex_t, edge_t, weight_t, multi_gpu>(handle_,
graph_view,
hubs.data(),
authorities.data(),
epsilon_,
max_iterations_,
has_initial_hubs_guess,
normalize_,
do_expensive_check_);
cugraph::hits<vertex_t, edge_t, weight_t, multi_gpu>(
handle_,
graph_view,
hubs.data(),
authorities.data(),
epsilon_,
max_iterations_,
(initial_hubs_guess_vertices_ != nullptr),
normalize_,
do_expensive_check_);

rmm::device_uvector<vertex_t> vertex_ids(graph_view.get_number_of_local_vertices(),
handle_.get_stream());
raft::copy(vertex_ids.data(), number_map->data(), vertex_ids.size(), handle_.get_stream());
#else
unsupported();
#endif

result_ = new cugraph::c_api::cugraph_hits_result_t{
new cugraph::c_api::cugraph_type_erased_device_array_t(vertex_ids, graph_->vertex_type_),
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/c_api/pagerank.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ struct pagerank_functor : public abstract_functor {

auto number_map = reinterpret_cast<rmm::device_uvector<vertex_t>*>(graph_->number_map_);

rmm::device_uvector<vertex_t> vertex_ids(graph_view.get_number_of_local_vertices(),
handle_.get_stream());
rmm::device_uvector<weight_t> pageranks(graph_view.get_number_of_local_vertices(),
handle_.get_stream());

Expand Down Expand Up @@ -145,6 +143,8 @@ struct pagerank_functor : public abstract_functor {
has_initial_guess_,
do_expensive_check_);

rmm::device_uvector<vertex_t> vertex_ids(graph_view.get_number_of_local_vertices(),
handle_.get_stream());
raft::copy(vertex_ids.data(), number_map->data(), vertex_ids.size(), handle_.get_stream());

result_ = new cugraph_pagerank_result_t{
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/c_api/sssp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ struct sssp_functor : public abstract_functor {
auto number_map = reinterpret_cast<rmm::device_uvector<vertex_t>*>(graph_->number_map_);

rmm::device_uvector<vertex_t> source_ids(1, handle_.get_stream());
rmm::device_uvector<vertex_t> vertex_ids(graph->get_number_of_vertices(),
handle_.get_stream());
rmm::device_uvector<weight_t> distances(graph->get_number_of_vertices(),
handle_.get_stream());
rmm::device_uvector<vertex_t> predecessors(0, handle_.get_stream());
Expand Down Expand Up @@ -117,6 +115,8 @@ struct sssp_functor : public abstract_functor {
static_cast<weight_t>(cutoff_),
do_expensive_check_);

rmm::device_uvector<vertex_t> vertex_ids(graph->get_number_of_vertices(),
handle_.get_stream());
raft::copy(vertex_ids.data(), number_map->data(), vertex_ids.size(), handle_.get_stream());

if (compute_predecessors_) {
Expand Down
Loading

0 comments on commit 87be0b3

Please sign in to comment.