Skip to content

Commit

Permalink
Implement C/CUDA RandomWalks functionality (#1439)
Browse files Browse the repository at this point in the history
This PR tracks work on issue: #1380.

Authors:
  - Andrei Schaffer (@aschaffer)

Approvers:
  - Brad Rees (@BradReesWork)
  - Chuck Hastings (@ChuckHastings)
  - Seunghwa Kang (@seunghwak)

URL: #1439
  • Loading branch information
aschaffer authored Mar 30, 2021
1 parent 22e9e2b commit f2e5a87
Show file tree
Hide file tree
Showing 11 changed files with 2,256 additions and 0 deletions.
1 change: 1 addition & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ add_library(cugraph SHARED
src/community/triangles_counting.cu
src/community/extract_subgraph_by_vertex.cu
src/community/egonet.cu
src/sampling/random_walks.cu
src/cores/core_number.cu
src/traversal/two_hop_neighbors.cu
src/components/connectivity.cu
Expand Down
28 changes: 28 additions & 0 deletions cpp/include/algorithms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1252,5 +1252,33 @@ extract_ego(raft::handle_t const &handle,
vertex_t *source_vertex,
vertex_t n_subgraphs,
vertex_t radius);

/**
* @brief returns random walks (RW) from starting sources, where each path is of given maximum
* length. Uniform distribution is assumed for the random engine.
*
* @tparam graph_t Type of graph/view (typically, graph_view_t).
* @tparam index_t Type used to store indexing and sizes.
* @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 Graph (view )object to generate RW on.
* @param ptr_d_start Device pointer to set of starting vertex indices for the RW.
* @param num_paths = number(paths).
* @param max_depth maximum length of RWs.
* @return std::tuple<device_vec_t<vertex_t>, device_vec_t<weight_t>,
* device_vec_t<index_t>> Triplet of coalesced RW paths, with corresponding edge weights for
* each, and corresponding path sizes. This is meant to minimize the number of DF's to be passed to
* the Python layer. The meaning of "coalesced" here is that a 2D array of paths of different sizes
* is represented as a 1D array.
*/
template <typename graph_t, typename index_t>
std::tuple<rmm::device_uvector<typename graph_t::vertex_type>,
rmm::device_uvector<typename graph_t::weight_type>,
rmm::device_uvector<index_t>>
random_walks(raft::handle_t const &handle,
graph_t const &graph,
typename graph_t::vertex_type const *ptr_d_start,
index_t num_paths,
index_t max_depth);
} // namespace experimental
} // namespace cugraph
24 changes: 24 additions & 0 deletions cpp/include/utilities/cython.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <graph.hpp>
#include <raft/handle.hpp>
#include <rmm/device_uvector.hpp>
#include <utilities/graph_traits.hpp>

namespace cugraph {
namespace cython {
Expand Down Expand Up @@ -185,6 +186,19 @@ struct major_minor_weights_t {
rmm::device_uvector<weight_t> shuffled_weights_;
};

// aggregate for random_walks() return type
// to be exposed to cython:
//
struct random_walk_ret_t {
size_t coalesced_sz_v_;
size_t coalesced_sz_w_;
size_t num_paths_;
size_t max_depth_;
std::unique_ptr<rmm::device_buffer> d_coalesced_v_;
std::unique_ptr<rmm::device_buffer> d_coalesced_w_;
std::unique_ptr<rmm::device_buffer> d_sizes_;
};

// wrapper for renumber_edgelist() return
// (unrenumbering maps, etc.)
//
Expand Down Expand Up @@ -442,6 +456,16 @@ std::unique_ptr<cy_multi_edgelists_t> call_egonet(raft::handle_t const& handle,
vertex_t* source_vertex,
vertex_t n_subgraphs,
vertex_t radius);
// wrapper for random_walks.
//
template <typename vertex_t, typename edge_t>
std::enable_if_t<cugraph::experimental::is_vertex_edge_combo<vertex_t, edge_t>::value,
std::unique_ptr<random_walk_ret_t>>
call_random_walks(raft::handle_t const& handle,
graph_container_t const& graph_container,
vertex_t const* ptr_start_set,
edge_t num_paths,
edge_t max_depth);

// wrapper for shuffling:
//
Expand Down
61 changes: 61 additions & 0 deletions cpp/include/utilities/graph_traits.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2021, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <type_traits>

namespace cugraph {
namespace experimental {

// primary template:
//
template <typename Src, typename... Types>
struct is_one_of; // purposely empty

// partial specializations:
//
template <typename Src, typename Head, typename... Tail>
struct is_one_of<Src, Head, Tail...> {
static constexpr bool value = std::is_same<Src, Head>::value || is_one_of<Src, Tail...>::value;
};

template <typename Src>
struct is_one_of<Src> {
static constexpr bool value = false;
};

// meta-function that constrains
// vertex_t and edge_t template param candidates:
//
template <typename vertex_t, typename edge_t>
struct is_vertex_edge_combo {
static constexpr bool value = is_one_of<vertex_t, int32_t, int64_t>::value &&
is_one_of<edge_t, int32_t, int64_t>::value &&
(sizeof(vertex_t) <= sizeof(edge_t));
};

// meta-function that constrains
// all 3 template param candidates:
//
template <typename vertex_t, typename edge_t, typename weight_t>
struct is_candidate {
static constexpr bool value =
is_vertex_edge_combo<vertex_t, edge_t>::value && is_one_of<weight_t, float, double>::value;
};

} // namespace experimental
} // namespace cugraph
Loading

0 comments on commit f2e5a87

Please sign in to comment.