From 88add92217925f19b1358a6e698a38d760b9d57b Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 01:51:54 +0200 Subject: [PATCH 01/26] Lookup edge src dst using edge id and type --- cpp/CMakeLists.txt | 2 + cpp/include/cugraph/algorithms.hpp | 81 ++ .../cugraph/src_dst_lookup_container.hpp | 93 ++ cpp/src/lookup/lookup_src_dst.cu | 893 ++++++++++++++++++ cpp/src/lookup/src_dst_lookup_container.cu | 378 ++++++++ cpp/tests/CMakeLists.txt | 33 +- cpp/tests/lookup/lookup_src_dst_test.cpp | 310 ++++++ cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 339 +++++++ 8 files changed, 2116 insertions(+), 13 deletions(-) create mode 100644 cpp/include/cugraph/src_dst_lookup_container.hpp create mode 100644 cpp/src/lookup/lookup_src_dst.cu create mode 100644 cpp/src/lookup/src_dst_lookup_container.cu create mode 100644 cpp/tests/lookup/lookup_src_dst_test.cpp create mode 100644 cpp/tests/lookup/mg_lookup_src_dst_test.cpp diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 2527599fece..e0a66562f30 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -171,6 +171,8 @@ set(CUGRAPH_SOURCES src/utilities/shuffle_vertices.cu src/detail/permute_range.cu src/utilities/shuffle_vertex_pairs.cu + src/lookup/lookup_src_dst.cu + src/lookup/src_dst_lookup_container.cu src/detail/collect_local_vertex_values.cu src/detail/groupby_and_count.cu src/detail/collect_comm_wrapper.cu diff --git a/cpp/include/cugraph/algorithms.hpp b/cpp/include/cugraph/algorithms.hpp index cc42399f091..c257ba7dd30 100644 --- a/cpp/include/cugraph/algorithms.hpp +++ b/cpp/include/cugraph/algorithms.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -2412,6 +2413,86 @@ std::tuple, weight_t> approximate_weighted_matchin raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_weight_view); + +/* + * @brief Build map to lookup source and destination using edge id and type + * + * @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 edge_type_t Type of edge types. 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_id_view View object holding edge ids of the edges of the graph pointed @p graph_view + * @param edge_type_view View object holding edge types of the edges of the graph pointed @p + * graph_view + * @return An object of type cugraph::search_container_t that encapsulates edge id and type to + * source and destination lookup map. + */ +template +search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +/* + * @brief Lookup edge sources and destinations using edge ids and an edge type + * + * @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 edge_type_t Type of edge types. 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 search_container Object of type cugraph::search_container_t that encapsulates edge id and + * type to source and destination lookup map. + * @param edge_ids_to_lookup Device span of edge ids to lookup + * @param edge_type_to_lookup Type of the edges corresponding to edge ids in @p edge_ids_to_lookup + * @return A tuple of device vector containing edge sources and destinations for edge ids + * in @p edge_ids_to_lookup and edge type @. If an edge id in @p edge_ids_to_lookup or + * edge type @edge_type_to_lookup is not found, the corresponding entry in the device vectors of + * the returned tuple will contain cugraph::invalid_vertex_id. + */ +template +std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& + search_container, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup); + +/* + * @brief Lookup edge sources and destinations using edge ids and edge types + * + * @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 edge_type_t Type of edge types. 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 search_container Object of type cugraph::search_container_t that encapsulates edge id and + * type to source and destination lookup map. + * @param edge_ids_to_lookup Device span of edge ids to lookup + * @param edge_types_to_lookup Device span of edge types corresponding to the edge ids + * in @p edge_ids_to_lookup + * @return A tuple of device vector containing edge sources and destinations for the edge ids + * in @p edge_ids_to_lookup and the edge types in @p edge_types_to_lookup. If an edge id in + * @p edge_ids_to_lookup or edge type in @p edge_types_to_lookup is not found, the + * corresponding entry in the device vectors of the returned tuple will contain + * cugraph::invalid_vertex_id. + */ +template +std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& + search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); } // namespace cugraph /** diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp new file mode 100644 index 00000000000..d1c835413b1 --- /dev/null +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 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. + * 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 +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +namespace cugraph { + +namespace detail { + +template +constexpr TupleType invalid_of_thrust_tuple_of_integral(std::index_sequence) +{ + return thrust::make_tuple( + cugraph::invalid_idx::type>::value...); +} +} // namespace detail + +template +constexpr TupleType invalid_of_thrust_tuple_of_integral() +{ + return detail::invalid_of_thrust_tuple_of_integral( + std::make_index_sequence::value>()); +} + +template +class search_container_t { + template + struct impl; + std::unique_ptr> pimpl; + + public: + using edge_id_type = edge_id_t; + using edge_type_type = edge_type_t; + using value_type = value_t; + + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + static_assert(is_arithmetic_or_thrust_tuple_of_arithmetic::value); + + ~search_container_t(); + search_container_t(); + search_container_t(raft::handle_t const& handle, + std::vector types, + std::vector type_counts); + search_container_t(const search_container_t&); + + void insert(raft::handle_t const& handle, + edge_type_t typ, + raft::device_span edge_ids_to_insert, + decltype(cugraph::allocate_dataframe_buffer( + 0, rmm::cuda_stream_view{}))&& values_to_insert); + + std::optional(0, rmm::cuda_stream_view{}))> + lookup_src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const; + + std::optional(0, rmm::cuda_stream_view{}))> + lookup_src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const; + void print() const; +}; + +} // namespace cugraph diff --git a/cpp/src/lookup/lookup_src_dst.cu b/cpp/src/lookup/lookup_src_dst.cu new file mode 100644 index 00000000000..6d6e7719e71 --- /dev/null +++ b/cpp/src/lookup/lookup_src_dst.cu @@ -0,0 +1,893 @@ +/* + * Copyright (c) 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. + * 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. + */ +#include "prims/kv_store.cuh" +#include "utilities/collect_comm.cuh" + +#include +#include +#include +#include +#include +#include + +#include + +namespace cugraph { +namespace detail { +template +std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup) +{ + using value_t = typename EdgeTypeAndIdToSrcDstLookupContainerType::value_type; + + static_assert(std::is_same_v>); + + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + static_assert(is_arithmetic_or_thrust_tuple_of_arithmetic::value); + + static_assert( + std::is_same_v, + "edge_id_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_id_type"); + static_assert( + std::is_same_v, + "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); + + rmm::device_uvector output_srcs(edge_ids_to_lookup.size(), handle.get_stream()); + rmm::device_uvector output_dsts(edge_ids_to_lookup.size(), handle.get_stream()); + + auto constexpr invalid_vertex_id = cugraph::invalid_vertex_id::value; + thrust::fill( + handle.get_thrust_policy(), output_srcs.begin(), output_srcs.end(), invalid_vertex_id); + thrust::fill( + handle.get_thrust_policy(), output_dsts.begin(), output_dsts.end(), invalid_vertex_id); + + auto optional_value_buffer = search_container.lookup_src_dst_from_edge_id_and_type( + handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); + + if (optional_value_buffer.has_value()) { + thrust::copy( + handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), + cugraph::get_dataframe_buffer_end((*optional_value_buffer)), + thrust::make_zip_iterator(thrust::make_tuple(output_srcs.begin(), output_dsts.begin()))); + } + return std::make_tuple(std::move(output_srcs), std::move(output_dsts)); +} + +template +std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup) +{ + using value_t = typename EdgeTypeAndIdToSrcDstLookupContainerType::value_type; + + static_assert(std::is_same_v>); + + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + static_assert(is_arithmetic_or_thrust_tuple_of_arithmetic::value); + + assert(edge_ids_to_lookup.size() == edge_types_to_lookup.size()); + + static_assert( + std::is_same_v, + "edge_id_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_id_type"); + static_assert( + std::is_same_v, + "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); + + rmm::device_uvector output_srcs(edge_ids_to_lookup.size(), handle.get_stream()); + rmm::device_uvector output_dsts(edge_ids_to_lookup.size(), handle.get_stream()); + + auto constexpr invalid_vertex_id = cugraph::invalid_vertex_id::value; + thrust::fill( + handle.get_thrust_policy(), output_srcs.begin(), output_srcs.end(), invalid_vertex_id); + thrust::fill( + handle.get_thrust_policy(), output_dsts.begin(), output_dsts.end(), invalid_vertex_id); + + auto optional_value_buffer = search_container.lookup_src_dst_from_edge_id_and_type( + handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); + + if (optional_value_buffer.has_value()) { + thrust::copy( + handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), + cugraph::get_dataframe_buffer_end((*optional_value_buffer)), + thrust::make_zip_iterator(thrust::make_tuple(output_srcs.begin(), output_dsts.begin()))); + } + return std::make_tuple(std::move(output_srcs), std::move(output_dsts)); +} + +template +EdgeTypeAndIdToSrcDstLookupContainerType create_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + GraphViewType const& graph_view, + EdgeIdInputWrapper edge_id_view, + EdgeTypeInputWrapper edge_type_view) +{ + static_assert(!std::is_same_v, + "Can not create edge id lookup table without edge ids"); + + using vertex_t = typename GraphViewType::vertex_type; + using edge_t = typename GraphViewType::edge_type; + using edge_type_t = typename EdgeTypeInputWrapper::value_type; + using edge_id_t = typename EdgeIdInputWrapper::value_type; + using value_t = typename EdgeTypeAndIdToSrcDstLookupContainerType::value_type; + + constexpr bool multi_gpu = GraphViewType::is_multi_gpu; + + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + static_assert(is_arithmetic_or_thrust_tuple_of_arithmetic::value); + + static_assert(std::is_same_v>); + + static_assert( + std::is_same_v, + "edge_type_t must match with EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type"); + + static_assert( + std::is_same_v, + "edge_id_t must match with typename EdgeTypeAndIdToSrcDstLookupContainerType::edge_id_type"); + + std::vector h_types_to_this_gpu{}; + std::vector h_freq_of_types_to_this_gpu{}; + std::unordered_map edge_type_to_count_map{}; + + for (size_t local_ep_idx = 0; local_ep_idx < graph_view.number_of_local_edge_partitions(); + ++local_ep_idx) { + // + // Copy edge ids and types + // + + auto number_of_edges_partition = + graph_view.local_edge_partition_view(local_ep_idx).number_of_edges(); + auto number_of_active_edges_partition = number_of_edges_partition; + + if (graph_view.has_edge_mask()) { + number_of_active_edges_partition = + detail::count_set_bits(handle, + (*(graph_view.edge_mask_view())).value_firsts()[local_ep_idx], + number_of_edges_partition); + } + + [[maybe_unused]] auto edgelist_ids = std::make_optional>( + number_of_active_edges_partition, handle.get_stream()); + + auto edgelist_types = std::make_optional>( + number_of_active_edges_partition, handle.get_stream()); + + auto edge_partition_mask_view = + graph_view.has_edge_mask() + ? std::make_optional< + detail::edge_partition_edge_property_device_view_t>( + *(graph_view.edge_mask_view()), local_ep_idx) + : std::nullopt; + + if (edge_partition_mask_view) { + if constexpr (multi_gpu) { + detail::copy_if_mask_set( + handle, + edge_id_view.value_firsts()[local_ep_idx], + edge_id_view.value_firsts()[local_ep_idx] + number_of_edges_partition, + (*edge_partition_mask_view).value_first(), + (*edgelist_ids).begin()); + } + detail::copy_if_mask_set( + handle, + edge_type_view.value_firsts()[local_ep_idx], + edge_type_view.value_firsts()[local_ep_idx] + number_of_edges_partition, + (*edge_partition_mask_view).value_first(), + (*edgelist_types).begin()); + + } else { + if constexpr (multi_gpu) { + thrust::copy(handle.get_thrust_policy(), + edge_id_view.value_firsts()[local_ep_idx], + edge_id_view.value_firsts()[local_ep_idx] + number_of_edges_partition, + (*edgelist_ids).begin()); + } + thrust::copy(handle.get_thrust_policy(), + edge_type_view.value_firsts()[local_ep_idx], + edge_type_view.value_firsts()[local_ep_idx] + number_of_edges_partition, + (*edgelist_types).begin()); + } + + std::vector h_unique_gpu_ids{}; + std::vector h_gpu_offsets{}; + + if constexpr (multi_gpu) { + // + // Count number of edge ids mapped to each GPU + // + + auto& comm = handle.get_comms(); + auto const comm_size = comm.get_size(); + auto& major_comm = handle.get_subcomm(cugraph::partition_manager::major_comm_name()); + auto const major_comm_size = major_comm.get_size(); + auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); + auto const minor_comm_size = minor_comm.get_size(); + + // destination gpu id from edge id. NB: edgelist_ids will holds gpu ids after the following + // thrust::transform + thrust::transform(handle.get_thrust_policy(), + (*edgelist_ids).begin(), + (*edgelist_ids).end(), + (*edgelist_ids).begin(), + [key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ + comm_size, major_comm_size, minor_comm_size}] __device__(auto eid) { + return key_func(eid); + }); + + thrust::sort(handle.get_thrust_policy(), + thrust::make_zip_iterator( + thrust::make_tuple((*edgelist_ids).begin(), (*edgelist_types).begin())), + thrust::make_zip_iterator( + thrust::make_tuple((*edgelist_ids).end(), (*edgelist_types).end()))); + + auto nr_unique_gpu_ids = + thrust::count_if(handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator((*edgelist_ids).size()), + detail::is_first_in_run_t{(*edgelist_ids).data()}); + + rmm::device_uvector unique_gpu_ids(nr_unique_gpu_ids, handle.get_stream()); + rmm::device_uvector gpu_offsets(nr_unique_gpu_ids + 1, handle.get_stream()); + + thrust::fill(handle.get_thrust_policy(), gpu_offsets.begin(), gpu_offsets.end(), edge_t{0}); + + thrust::reduce_by_key(handle.get_thrust_policy(), + (*edgelist_ids).begin(), + (*edgelist_ids).end(), + thrust::make_constant_iterator(size_t{1}), + unique_gpu_ids.begin(), + gpu_offsets.begin()); + + thrust::exclusive_scan(handle.get_thrust_policy(), + gpu_offsets.begin(), + gpu_offsets.end(), + gpu_offsets.begin(), + size_t{0}); + + h_unique_gpu_ids.resize(unique_gpu_ids.size()); + h_gpu_offsets.resize(gpu_offsets.size()); + raft::update_host( + h_unique_gpu_ids.data(), unique_gpu_ids.data(), unique_gpu_ids.size(), handle.get_stream()); + raft::update_host( + h_gpu_offsets.data(), gpu_offsets.data(), gpu_offsets.size(), handle.get_stream()); + + } else { + thrust::sort(handle.get_thrust_policy(), (*edgelist_types).begin(), (*edgelist_types).end()); + + h_unique_gpu_ids.resize(size_t{1}); + h_unique_gpu_ids[0] = 0; + + h_gpu_offsets.resize(h_unique_gpu_ids.size() + 1); + h_gpu_offsets[0] = 0; + h_gpu_offsets[1] = (*edgelist_types).size(); + } + + // + // For edge ids mapped to each gpu, count number of unique types and elements per type. + // cub::DeviceSegmentedReduce(ByKey) ??? + // + + [[maybe_unused]] std::vector h_gpu_ids_partition{}; + std::vector h_types_partition{}; + std::vector h_type_freqs_partition{}; + + rmm::device_uvector unique_types_segment(0, handle.get_stream()); + rmm::device_uvector type_freqs_segment(0, handle.get_stream()); + + for (size_t idx = 0; idx < h_unique_gpu_ids.size(); ++idx) { + auto gpu_id = h_unique_gpu_ids[idx]; + + auto nr_uniqe_types_segment = + thrust::count_if(handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator( + static_cast(h_gpu_offsets[idx + 1] - h_gpu_offsets[idx])), + detail::is_first_in_run_t{(*edgelist_types).data() + + h_gpu_offsets[idx]}); + + unique_types_segment.resize(nr_uniqe_types_segment, handle.get_stream()); + type_freqs_segment.resize(nr_uniqe_types_segment, handle.get_stream()); + + thrust::reduce_by_key(handle.get_thrust_policy(), + (*edgelist_types).begin() + h_gpu_offsets[idx], + (*edgelist_types).begin() + h_gpu_offsets[idx + 1], + thrust::make_constant_iterator(size_t{1}), + unique_types_segment.begin(), + type_freqs_segment.begin()); + + std::vector h_unique_types_segment(nr_uniqe_types_segment); + std::vector h_type_freqs_segment(nr_uniqe_types_segment); + + raft::update_host(h_unique_types_segment.data(), + unique_types_segment.data(), + unique_types_segment.size(), + handle.get_stream()); + raft::update_host(h_type_freqs_segment.data(), + type_freqs_segment.data(), + type_freqs_segment.size(), + handle.get_stream()); + + if constexpr (multi_gpu) { + h_gpu_ids_partition.insert(h_gpu_ids_partition.end(), nr_uniqe_types_segment, gpu_id); + } + + h_types_partition.insert( + h_types_partition.end(), h_unique_types_segment.begin(), h_unique_types_segment.end()); + h_type_freqs_partition.insert( + h_type_freqs_partition.end(), h_type_freqs_segment.begin(), h_type_freqs_segment.end()); + } + + [[maybe_unused]] rmm::device_uvector gpu_ids_partition(h_gpu_ids_partition.size(), + handle.get_stream()); + rmm::device_uvector types_partition(h_types_partition.size(), handle.get_stream()); + rmm::device_uvector type_freqs_partition(h_type_freqs_partition.size(), + handle.get_stream()); + + if constexpr (multi_gpu) { + raft::update_device(gpu_ids_partition.data(), + h_gpu_ids_partition.data(), + h_gpu_ids_partition.size(), + handle.get_stream()); + } + raft::update_device(types_partition.data(), + h_types_partition.data(), + h_types_partition.size(), + handle.get_stream()); + raft::update_device(type_freqs_partition.data(), + h_type_freqs_partition.data(), + h_type_freqs_partition.size(), + handle.get_stream()); + + if constexpr (multi_gpu) { + // Shuffle to the proper GPUs + std::forward_as_tuple(std::tie(gpu_ids_partition, types_partition, type_freqs_partition), + std::ignore) = + cugraph::groupby_gpu_id_and_shuffle_values( + handle.get_comms(), + thrust::make_zip_iterator(thrust::make_tuple( + gpu_ids_partition.begin(), types_partition.begin(), type_freqs_partition.begin())), + thrust::make_zip_iterator(thrust::make_tuple( + gpu_ids_partition.end(), types_partition.end(), type_freqs_partition.end())), + [] __device__(auto val) { return thrust::get<0>(val); }, + handle.get_stream()); + + thrust::for_each( + handle.get_thrust_policy(), + gpu_ids_partition.begin(), + gpu_ids_partition.end(), + [rank = handle.get_comms().get_rank()] __device__(auto val) { assert(val == rank); }); + } + + thrust::sort_by_key(handle.get_thrust_policy(), + types_partition.begin(), + types_partition.end(), + type_freqs_partition.begin()); + + auto nr_uniqe_types_partition = + thrust::count_if(handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator(types_partition.size()), + detail::is_first_in_run_t{types_partition.data()}); + + rmm::device_uvector unique_types_partition(nr_uniqe_types_partition, + handle.get_stream()); + rmm::device_uvector unique_type_freqs_partition(nr_uniqe_types_partition, + handle.get_stream()); + + thrust::reduce_by_key(handle.get_thrust_policy(), + types_partition.begin(), + types_partition.end(), + type_freqs_partition.begin(), + unique_types_partition.begin(), + unique_type_freqs_partition.begin()); + + std::vector h_unique_types_partition(nr_uniqe_types_partition); + std::vector h_unique_type_freqs_partition(nr_uniqe_types_partition); + + raft::update_host(h_unique_types_partition.data(), + unique_types_partition.data(), + unique_types_partition.size(), + handle.get_stream()); + + raft::update_host(h_unique_type_freqs_partition.data(), + unique_type_freqs_partition.data(), + unique_type_freqs_partition.size(), + handle.get_stream()); + + for (edge_type_t idx = 0; idx < nr_uniqe_types_partition; idx++) { + auto typ = h_unique_types_partition[idx]; + auto freq = h_unique_type_freqs_partition[idx]; + if (edge_type_to_count_map.find(typ) != edge_type_to_count_map.end()) { + edge_type_to_count_map[typ] += freq; + } else { + edge_type_to_count_map[typ] = freq; + } + } + + h_types_to_this_gpu.insert( + h_types_to_this_gpu.end(), h_unique_types_partition.begin(), h_unique_types_partition.end()); + + h_freq_of_types_to_this_gpu.insert(h_freq_of_types_to_this_gpu.end(), + h_unique_type_freqs_partition.begin(), + h_unique_type_freqs_partition.end()); + } + + // + // Find global unique types and their frequencies + // + rmm::device_uvector types_to_this_gpu(h_types_to_this_gpu.size(), + handle.get_stream()); + + rmm::device_uvector freq_of_types_to_this_gpu(h_freq_of_types_to_this_gpu.size(), + handle.get_stream()); + + raft::update_device(types_to_this_gpu.data(), + h_types_to_this_gpu.data(), + h_types_to_this_gpu.size(), + handle.get_stream()); + + raft::update_device(freq_of_types_to_this_gpu.data(), + h_freq_of_types_to_this_gpu.data(), + h_freq_of_types_to_this_gpu.size(), + handle.get_stream()); + + thrust::sort_by_key(handle.get_thrust_policy(), + types_to_this_gpu.begin(), + types_to_this_gpu.end(), + freq_of_types_to_this_gpu.begin()); + + auto nr_unique_types_this_gpu = + thrust::count_if(handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator(types_to_this_gpu.size()), + detail::is_first_in_run_t{types_to_this_gpu.data()}); + + rmm::device_uvector unique_types_to_this_gpu(nr_unique_types_this_gpu, + handle.get_stream()); + rmm::device_uvector freq_of_unique_types_this_gpu(nr_unique_types_this_gpu, + handle.get_stream()); + + thrust::reduce_by_key(handle.get_thrust_policy(), + types_to_this_gpu.begin(), + types_to_this_gpu.end(), + freq_of_types_to_this_gpu.begin(), + unique_types_to_this_gpu.begin(), + freq_of_unique_types_this_gpu.begin()); + + rmm::device_uvector global_unique_types(nr_unique_types_this_gpu, + handle.get_stream()); + + thrust::transform(handle.get_thrust_policy(), + unique_types_to_this_gpu.begin(), + unique_types_to_this_gpu.end(), + global_unique_types.begin(), + [] __device__(auto val) { return int{val}; }); + + auto nr_unique_types_global = nr_unique_types_this_gpu; + + if constexpr (multi_gpu) { + global_unique_types = cugraph::detail::shuffle_ext_vertices_to_local_gpu_by_vertex_partitioning( + handle, std::move(global_unique_types)); + + thrust::sort( + handle.get_thrust_policy(), global_unique_types.begin(), global_unique_types.end()); + + auto nr_unique_elements = static_cast(thrust::distance( + global_unique_types.begin(), + thrust::unique( + handle.get_thrust_policy(), global_unique_types.begin(), global_unique_types.end()))); + + global_unique_types.resize(nr_unique_elements, handle.get_stream()); + + nr_unique_types_global = host_scalar_allreduce( + handle.get_comms(), nr_unique_elements, raft::comms::op_t::SUM, handle.get_stream()); + + global_unique_types = detail::device_allgatherv( + handle, + handle.get_comms(), + raft::device_span{global_unique_types.data(), global_unique_types.size()}); + + assert(global_unique_types.size() == nr_unique_types_global); + } + + std::vector h_unique_types_global(nr_unique_types_global); + + raft::update_host(h_unique_types_global.data(), + global_unique_types.data(), + global_unique_types.size(), + handle.get_stream()); + + // + // Create search container with appropriate capacity + // + + std::vector local_freqs(h_unique_types_global.size(), 0); + + for (size_t idx = 0; idx < h_unique_types_global.size(); idx++) { + auto typ = h_unique_types_global[idx]; + auto search_itr = edge_type_to_count_map.find(typ); + size_t store_capacity = (search_itr != edge_type_to_count_map.end()) ? search_itr->second : 0; + local_freqs[idx] = store_capacity; + } + + auto search_container = + EdgeTypeAndIdToSrcDstLookupContainerType(handle, h_unique_types_global, local_freqs); + + // + // Populate the search container + // + + for (size_t local_ep_idx = 0; local_ep_idx < graph_view.number_of_local_edge_partitions(); + ++local_ep_idx) { + // + // decompress one edge_partition at a time + // + + auto number_of_local_edges = + graph_view.local_edge_partition_view(local_ep_idx).number_of_edges(); + + if (graph_view.has_edge_mask()) { + number_of_local_edges = + detail::count_set_bits(handle, + (*(graph_view.edge_mask_view())).value_firsts()[local_ep_idx], + number_of_local_edges); + } + + rmm::device_uvector edgelist_majors(number_of_local_edges, handle.get_stream()); + rmm::device_uvector edgelist_minors(edgelist_majors.size(), handle.get_stream()); + auto edgelist_ids = + std::make_optional>(edgelist_majors.size(), handle.get_stream()); + auto edgelist_types = std::make_optional>( + edgelist_majors.size(), handle.get_stream()); + + detail::decompress_edge_partition_to_edgelist( + handle, + edge_partition_device_view_t( + graph_view.local_edge_partition_view(local_ep_idx)), + std::nullopt, + std::make_optional>( + edge_id_view, local_ep_idx), + std::make_optional< + detail::edge_partition_edge_property_device_view_t>( + edge_type_view, local_ep_idx), + graph_view.has_edge_mask() + ? std::make_optional< + detail::edge_partition_edge_property_device_view_t>( + *(graph_view.edge_mask_view()), local_ep_idx) + : std::nullopt, + raft::device_span(edgelist_majors.data(), number_of_local_edges), + raft::device_span(edgelist_minors.data(), number_of_local_edges), + std::nullopt, + std::make_optional>((*edgelist_ids).data(), number_of_local_edges), + std::make_optional>((*edgelist_types).data(), + number_of_local_edges), + graph_view.local_edge_partition_segment_offsets(local_ep_idx)); + + // + // Shuffle to the right GPUs using edge ids as keys + // + + if constexpr (multi_gpu) { + auto const comm_size = handle.get_comms().get_size(); + auto& major_comm = handle.get_subcomm(cugraph::partition_manager::major_comm_name()); + auto const major_comm_size = major_comm.get_size(); + auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); + auto const minor_comm_size = minor_comm.get_size(); + + // Shuffle to the proper GPUs + std::forward_as_tuple( + std::tie(edgelist_majors, edgelist_minors, (*edgelist_ids), (*edgelist_types)), + std::ignore) = + cugraph::groupby_gpu_id_and_shuffle_values( + handle.get_comms(), + thrust::make_zip_iterator(thrust::make_tuple(edgelist_majors.begin(), + edgelist_minors.begin(), + (*edgelist_ids).begin(), + (*edgelist_types).begin())), + thrust::make_zip_iterator(thrust::make_tuple(edgelist_majors.end(), + edgelist_minors.end(), + (*edgelist_ids).end(), + (*edgelist_types).end())), + [key_func = + cugraph::detail::compute_gpu_id_from_ext_vertex_t{ + comm_size, major_comm_size, minor_comm_size}] __device__(auto val) { + return key_func(thrust::get<2>(val)); + }, + handle.get_stream()); + } + + // + // Sort by edge types and insert to type specific kv_store_t object + // + + auto itr_to_triple = thrust::make_zip_iterator( + edgelist_majors.begin(), edgelist_minors.begin(), (*edgelist_ids).begin()); + + thrust::sort_by_key(handle.get_thrust_policy(), + (*edgelist_types).begin(), + (*edgelist_types).end(), + itr_to_triple); + + auto nr_uniqe_edge_types_partition = + thrust::count_if(handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator((*edgelist_types).size()), + detail::is_first_in_run_t{(*edgelist_types).data()}); + + rmm::device_uvector unique_types(nr_uniqe_edge_types_partition, + handle.get_stream()); + rmm::device_uvector type_offsets(nr_uniqe_edge_types_partition + 1, + handle.get_stream()); + + thrust::fill(handle.get_thrust_policy(), type_offsets.begin(), type_offsets.end(), edge_t{0}); + + thrust::reduce_by_key(handle.get_thrust_policy(), + (*edgelist_types).begin(), + (*edgelist_types).end(), + thrust::make_constant_iterator(size_t{1}), + unique_types.begin(), + type_offsets.begin()); + + thrust::exclusive_scan(handle.get_thrust_policy(), + type_offsets.begin(), + type_offsets.end(), + type_offsets.begin(), + size_t{0}); + + std::vector h_unique_types(unique_types.size()); + std::vector h_type_offsets(type_offsets.size()); + + raft::update_host( + h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); + + raft::update_host( + h_type_offsets.data(), type_offsets.data(), type_offsets.size(), handle.get_stream()); + + for (size_t idx = 0; idx < h_unique_types.size(); idx++) { + auto typ = h_unique_types[idx]; + auto nr_elements_to_insert = (h_type_offsets[idx + 1] - h_type_offsets[idx]); + + auto values_to_insert = + cugraph::allocate_dataframe_buffer(nr_elements_to_insert, handle.get_stream()); + + auto zip_itr = thrust::make_zip_iterator( + thrust::make_tuple(edgelist_majors.begin(), edgelist_minors.begin())); + + // FIXME: Can we avoid copying + thrust::copy(handle.get_thrust_policy(), + zip_itr + h_type_offsets[idx], + zip_itr + h_type_offsets[idx] + nr_elements_to_insert, + cugraph::get_dataframe_buffer_begin(values_to_insert)); + + static_assert(std::is_same_v< + typename thrust::iterator_traits::value_type, + value_t>); + + search_container.insert( + handle, + typ, + raft::device_span((*edgelist_ids).begin() + h_type_offsets[idx], + nr_elements_to_insert), + std::move(values_to_insert)); + } + } + + return search_container; +} +} // namespace detail + +template +std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& + search_container, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup) +{ + using m_t = search_container_t>; + return detail:: + cugraph_lookup_src_dst_from_edge_id_and_type( + handle, search_container, edge_ids_to_lookup, edge_type_to_lookup); +} + +template +std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& + search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup) +{ + using m_t = search_container_t>; + return detail:: + cugraph_lookup_src_dst_from_edge_id_and_type( + handle, search_container, edge_ids_to_lookup, edge_types_to_lookup); +} + +template +search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view) +{ + using graph_view_t = graph_view_t; + using return_t = search_container_t>; + + return detail::create_edge_id_and_type_to_src_dst_lookup_map( + handle, graph_view, edge_id_view, edge_type_view); +} + +using edge_type_t = int32_t; + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t const edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template std::tuple, rmm::device_uvector> +cugraph_lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +} // namespace cugraph diff --git a/cpp/src/lookup/src_dst_lookup_container.cu b/cpp/src/lookup/src_dst_lookup_container.cu new file mode 100644 index 00000000000..f427509ddad --- /dev/null +++ b/cpp/src/lookup/src_dst_lookup_container.cu @@ -0,0 +1,378 @@ +/* + * Copyright (c) 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. + * 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. + */ +#include "detail/graph_partition_utils.cuh" +#include "prims/kv_store.cuh" +#include "utilities/collect_comm.cuh" + +#include +#include +#include +#include + +namespace cugraph { + +template +template +struct search_container_t::impl { + private: + using container_t = + std::unordered_map>; + using store_t = typename container_t::mapped_type; + container_t edge_type_to_kv_store; + + public: + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + ~impl() {} + impl() {} + impl(raft::handle_t const& handle, + std::vector typs, + std::vector typ_freqs) + { + auto invalid_key = cugraph::invalid_vertex_id::value; + auto invalid_value = invalid_of_thrust_tuple_of_integral(); + + edge_type_to_kv_store = container_t{}; + edge_type_to_kv_store.reserve(typs.size()); + + for (size_t idx = 0; idx < typs.size(); idx++) { + auto typ = typs[idx]; + size_t store_capacity = typ_freqs[idx]; + + edge_type_to_kv_store.insert( + {typ, std::move(store_t(store_capacity, invalid_key, invalid_value, handle.get_stream()))}); + } + } + + void print() const + { + for (const auto& [key, map] : edge_type_to_kv_store) { + std::cout << "key: " << key << " size: " << map.size() << std::endl; + } + } + + void insert(raft::handle_t const& handle, + edge_type_t type, + raft::device_span edge_ids_to_insert, + decltype(cugraph::allocate_dataframe_buffer( + 0, rmm::cuda_stream_view{}))&& values_to_insert) + { + auto itr = edge_type_to_kv_store.find(type); + + if (itr != edge_type_to_kv_store.end()) { + assert(itr->first == type); + + itr->second.insert(edge_ids_to_insert.begin(), + edge_ids_to_insert.end(), + cugraph::get_dataframe_buffer_begin(values_to_insert), + handle.get_stream()); + + } else { + assert(false); + } + } + + std::optional(0, rmm::cuda_stream_view{}))> + lookup_src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const + { + using store_t = typename container_t::mapped_type; + const store_t* kv_store_object{nullptr}; + + auto value_buffer = cugraph::allocate_dataframe_buffer(0, handle.get_stream()); + auto itr = edge_type_to_kv_store.find(edge_type_to_lookup); + + if (itr != edge_type_to_kv_store.end()) { + assert(edge_type_to_lookup == itr->first); + kv_store_object = &(itr->second); + + } else { + cugraph::resize_dataframe_buffer( + value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); + + auto invalid_value = invalid_of_thrust_tuple_of_integral(); + // Mark with invalid here + thrust::copy(handle.get_thrust_policy(), + thrust::make_constant_iterator(invalid_value), + thrust::make_constant_iterator(invalid_value) + edge_ids_to_lookup.size(), + cugraph::get_dataframe_buffer_begin(value_buffer)); + + return std::make_optional(std::move(value_buffer)); + } + + if (multi_gpu) { + auto& comm = handle.get_comms(); + auto const comm_size = comm.get_size(); + auto& major_comm = handle.get_subcomm(cugraph::partition_manager::major_comm_name()); + auto const major_comm_size = major_comm.get_size(); + auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); + auto const minor_comm_size = minor_comm.get_size(); + + auto key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ + comm_size, major_comm_size, minor_comm_size}; + + value_buffer = cugraph::collect_values_for_keys(handle, + kv_store_object->view(), + edge_ids_to_lookup.begin(), + edge_ids_to_lookup.end(), + key_func); + + } else { + cugraph::resize_dataframe_buffer( + value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); + + kv_store_object->view().find(edge_ids_to_lookup.begin(), + edge_ids_to_lookup.end(), + cugraph::get_dataframe_buffer_begin(value_buffer), + handle.get_stream()); + } + + return std::make_optional(std::move(value_buffer)); + } + + std::optional(0, rmm::cuda_stream_view{}))> + lookup_src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const + { + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + + assert(edge_ids_to_lookup.size() == edge_types_to_lookup.size()); + + rmm::device_uvector tmp_edge_ids_to_lookup(edge_ids_to_lookup.size(), + handle.get_stream()); + + rmm::device_uvector tmp_edge_types_to_lookup(edge_types_to_lookup.size(), + handle.get_stream()); + + rmm::device_uvector original_idxs(edge_ids_to_lookup.size(), handle.get_stream()); + + thrust::sequence( + handle.get_thrust_policy(), original_idxs.begin(), original_idxs.end(), edge_id_t{0}); + + thrust::copy(handle.get_thrust_policy(), + edge_ids_to_lookup.begin(), + edge_ids_to_lookup.end(), + tmp_edge_ids_to_lookup.begin()); + + thrust::copy(handle.get_thrust_policy(), + edge_types_to_lookup.begin(), + edge_types_to_lookup.end(), + tmp_edge_types_to_lookup.begin()); + + thrust::sort_by_key(handle.get_thrust_policy(), + tmp_edge_types_to_lookup.begin(), + tmp_edge_types_to_lookup.end(), + thrust::make_zip_iterator(thrust::make_tuple(tmp_edge_ids_to_lookup.begin(), + original_idxs.begin()))); + + auto nr_uniqe_edge_types_to_lookup = thrust::count_if( + handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator(tmp_edge_types_to_lookup.size()), + detail::is_first_in_run_t{tmp_edge_types_to_lookup.data()}); + + rmm::device_uvector unique_types(nr_uniqe_edge_types_to_lookup, + handle.get_stream()); + rmm::device_uvector type_offsets(nr_uniqe_edge_types_to_lookup + 1, + handle.get_stream()); + + thrust::fill( + handle.get_thrust_policy(), type_offsets.begin(), type_offsets.end(), edge_id_t{0}); + + thrust::reduce_by_key(handle.get_thrust_policy(), + tmp_edge_types_to_lookup.begin(), + tmp_edge_types_to_lookup.end(), + thrust::make_constant_iterator(size_t{1}), + unique_types.begin(), + type_offsets.begin()); + + thrust::exclusive_scan(handle.get_thrust_policy(), + type_offsets.begin(), + type_offsets.end(), + type_offsets.begin(), + size_t{0}); + + std::vector h_unique_types(unique_types.size()); + std::vector h_type_offsets(type_offsets.size()); + + raft::update_host( + h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); + + raft::update_host( + h_type_offsets.data(), type_offsets.data(), type_offsets.size(), handle.get_stream()); + + std::unordered_map typ_to_local_idx_map{}; + + RAFT_CUDA_TRY(cudaDeviceSynchronize()); + + for (size_t idx = 0; idx < h_unique_types.size(); idx++) { + typ_to_local_idx_map[h_unique_types[idx]] = idx; + } + + auto output_value_buffer = + cugraph::allocate_dataframe_buffer(edge_ids_to_lookup.size(), handle.get_stream()); + auto invalid_value = invalid_of_thrust_tuple_of_integral(); + thrust::fill(handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin(output_value_buffer), + cugraph::get_dataframe_buffer_begin(output_value_buffer), + invalid_value); + + if (multi_gpu) { + auto& comm = handle.get_comms(); + auto rx_counts = host_scalar_allgather(comm, unique_types.size(), handle.get_stream()); + std::vector rx_displacements(rx_counts.size()); + std::exclusive_scan(rx_counts.begin(), rx_counts.end(), rx_displacements.begin(), size_t{0}); + rmm::device_uvector rx_unique_types(rx_displacements.back() + rx_counts.back(), + handle.get_stream()); + + device_allgatherv(comm, + unique_types.begin(), + rx_unique_types.begin(), + rx_counts, + rx_displacements, + handle.get_stream()); + unique_types = std::move(rx_unique_types); + + thrust::sort(handle.get_thrust_policy(), unique_types.begin(), unique_types.end()); + + unique_types.resize( + thrust::distance( + unique_types.begin(), + thrust::unique(handle.get_thrust_policy(), unique_types.begin(), unique_types.end())), + handle.get_stream()); + } + + h_unique_types.resize(unique_types.size()); + raft::update_host( + h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); + + for (size_t idx = 0; idx < h_unique_types.size(); idx++) { + auto typ = h_unique_types[idx]; + + auto start_ptr = tmp_edge_ids_to_lookup.begin(); + size_t span_size = 0; + + if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { + auto xx = typ_to_local_idx_map[typ]; + + start_ptr = tmp_edge_ids_to_lookup.begin() + h_type_offsets[xx]; + span_size = h_type_offsets[xx + 1] - h_type_offsets[xx]; + } + + auto optional_value_buffer = lookup_src_dst_from_edge_id_and_type( + handle, raft::device_span{start_ptr, span_size}, typ, multi_gpu); + + if (optional_value_buffer.has_value()) { + if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { + thrust::copy(handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), + cugraph::get_dataframe_buffer_end((*optional_value_buffer)), + cugraph::get_dataframe_buffer_begin(output_value_buffer) + + h_type_offsets[typ_to_local_idx_map[typ]]); + } + } + } + + thrust::sort_by_key(handle.get_thrust_policy(), + original_idxs.begin(), + original_idxs.end(), + cugraph::get_dataframe_buffer_begin(output_value_buffer)); + + return std::make_optional(std::move(output_value_buffer)); + } +}; + +template +search_container_t::~search_container_t() +{ + pimpl.reset(); +} + +template +search_container_t::search_container_t() + : pimpl{std::make_unique>()} +{ +} + +template +search_container_t::search_container_t( + raft::handle_t const& handle, std::vector typs, std::vector typ_freqs) + : pimpl{std::make_unique>(handle, typs, typ_freqs)} +{ +} + +template +search_container_t::search_container_t(const search_container_t&) +{ +} + +template +void search_container_t::insert( + raft::handle_t const& handle, + edge_type_t type, + raft::device_span edge_ids_to_insert, + decltype(cugraph::allocate_dataframe_buffer(0, + rmm::cuda_stream_view{}))&& values_to_insert) +{ + pimpl->insert(handle, type, edge_ids_to_insert, std::move(values_to_insert)); +} + +template +std::optional(0, rmm::cuda_stream_view{}))> +search_container_t::lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const +{ + return pimpl->lookup_src_dst_from_edge_id_and_type( + handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); +} + +template +std::optional(0, rmm::cuda_stream_view{}))> +search_container_t::lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const +{ + return pimpl->lookup_src_dst_from_edge_id_and_type( + handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); +} + +template +void search_container_t::print() const +{ + pimpl->print(); +} + +template class search_container_t>; +template class search_container_t>; +template class search_container_t>; + +} // namespace cugraph diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index d1dd2dec069..b5c8b4bf038 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -310,11 +310,11 @@ ConfigureTest(LOUVAIN_TEST community/louvain_test.cpp) ConfigureTest(LEIDEN_TEST community/leiden_test.cpp) ################################################################################################### -# - WEIGHTED MATCHING tests ---------------------------------------------------------------------------------- +# - WEIGHTED MATCHING tests ----------------------------------------------------------------------- ConfigureTest(WEIGHTED_MATCHING_TEST community/weighted_matching_test.cpp) ################################################################################################### -# - Legacy ECG tests ------------------------------------------------------------------------------------- +# - Legacy ECG tests ------------------------------------------------------------------------------ ConfigureTest(LEGACY_ECG_TEST community/legacy_ecg_test.cpp) ################################################################################################### @@ -439,13 +439,13 @@ ConfigureTest(EDGE_BETWEENNESS_CENTRALITY_TEST centrality/edge_betweenness_centr # - WEAKLY CONNECTED COMPONENTS tests ------------------------------------------------------------- ConfigureTest(WEAKLY_CONNECTED_COMPONENTS_TEST components/weakly_connected_components_test.cpp) -############################################################################################### -# - MIS tests ------------------------------------------------------------------------------ +################################################################################################### +# - MIS tests ------------------------------------------------------------------------------------- ConfigureTest(MIS_TEST components/mis_test.cu) target_include_directories(MIS_TEST PRIVATE "${CUGRAPH_SOURCE_DIR}/src") -############################################################################################### -# - VERTEX COLORING tests ------------------------------------------------------------------- +################################################################################################### +# - VERTEX COLORING tests ---------------------------------------------------------------------- ConfigureTest(VERTEX_COLORING_TEST components/vertex_coloring_test.cu) target_include_directories(VERTEX_COLORING_TEST PRIVATE "${CUGRAPH_SOURCE_DIR}/src") @@ -454,7 +454,7 @@ target_include_directories(VERTEX_COLORING_TEST PRIVATE "${CUGRAPH_SOURCE_DIR}/s ConfigureTest(SIMILARITY_TEST link_prediction/similarity_test.cu) ################################################################################################### -# - WEIGHTED_SIMILARITY tests ------------------------------------------------------------------------------ +# - WEIGHTED_SIMILARITY tests --------------------------------------------------------------------- ConfigureTest(WEIGHTED_SIMILARITY_TEST link_prediction/weighted_similarity_test.cpp) ################################################################################################### @@ -482,8 +482,8 @@ ConfigureTest(CORE_NUMBER_TEST cores/core_number_test.cpp) # - Core Number tests ----------------------------------------------------------------------------- ConfigureTest(K_CORE_TEST cores/k_core_test.cpp) -############################################################################################### -# - K-truss tests -------------------------------------------------------------------------- +################################################################################################### +# - K-truss tests --------------------------------------------------------------------------------- ConfigureTest(K_TRUSS_TEST community/k_truss_test.cpp) ################################################################################################### @@ -491,9 +491,12 @@ ConfigureTest(K_TRUSS_TEST community/k_truss_test.cpp) ConfigureTest(TRIANGLE_COUNT_TEST community/triangle_count_test.cpp) ################################################################################################### -# - Edge Triangle Count tests -------------------------------------------------------------------------- +# - Edge Triangle Count tests --------------------------------------------------------------------- ConfigureTest(EDGE_TRIANGLE_COUNT_TEST community/edge_triangle_count_test.cpp) +################################################################################################### +# - EDGE SOURCE DESTINATION LOOKUP tests ---------------------------------------------------------- +ConfigureTestMG(LOOKUP_SRC_DST_TEST lookup/lookup_src_dst_test.cpp) ################################################################################################### # - K-hop Neighbors tests ------------------------------------------------------------------------- @@ -580,7 +583,7 @@ if(BUILD_CUGRAPH_MG_TESTS) ConfigureTestMG(MG_LEIDEN_TEST community/mg_leiden_test.cpp) ############################################################################################### - # - MG WEIGHTED MATCHING tests -------------------------------------------------------------------------- + # - MG WEIGHTED MATCHING tests ---------------------------------------------------------------- ConfigureTestMG(MG_WEIGHTED_MATCHING_TEST community/mg_weighted_matching_test.cpp) ############################################################################################### @@ -596,7 +599,7 @@ if(BUILD_CUGRAPH_MG_TESTS) ConfigureTestMG(MG_EGONET_TEST community/mg_egonet_test.cu) ############################################################################################### - # - MG EDGE TRIANGLE COUNT tests -------------------------------------------------------------------------- + # - MG EDGE TRIANGLE COUNT tests -------------------------------------------------------------- ConfigureTestMG(MG_EDGE_TRIANGLE_COUNT_TEST community/mg_edge_triangle_count_test.cpp) ############################################################################################### @@ -604,6 +607,10 @@ if(BUILD_CUGRAPH_MG_TESTS) ConfigureTestMG(MG_WEAKLY_CONNECTED_COMPONENTS_TEST components/mg_weakly_connected_components_test.cpp) + ############################################################################################### + # - MG EDGE SOURCE DESTINATION LOOKUP tests --------------------------------------------------- + ConfigureTestMG(MG_LOOKUP_SRC_DST_TEST lookup/mg_lookup_src_dst_test.cpp) + ############################################################################################### # - MG MIS tests ------------------------------------------------------------------------------ ConfigureTestMG(MG_MIS_TEST components/mg_mis_test.cu) @@ -714,7 +721,7 @@ if(BUILD_CUGRAPH_MG_TESTS) ConfigureTestMG(MG_RANDOM_WALKS_TEST sampling/mg_random_walks_test.cpp) ############################################################################################### - # - MG WEIGHTED_SIMILARITY tests ----------------------------------------------------------------------- + # - MG WEIGHTED_SIMILARITY tests -------------------------------------------------------------- ConfigureTestMG(MG_WEIGHTED_SIMILARITY_TEST link_prediction/mg_weighted_similarity_test.cpp) ############################################################################################### diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp new file mode 100644 index 00000000000..1272641c6ae --- /dev/null +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -0,0 +1,310 @@ + +/* + * Copyright (c) 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. + * 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 governin_from_mtxg permissions and + * limitations under the License. + */ + +#include "utilities/base_fixture.hpp" +#include "utilities/conversion_utilities.hpp" +#include "utilities/property_generator_utilities.hpp" +#include "utilities/test_graphs.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +struct EdgeSrcDstLookup_UseCase { + bool edge_masking{false}; + bool check_correctness{true}; +}; + +template +class Tests_SGLookupEdgeSrcDst + : public ::testing::TestWithParam> { + public: + Tests_SGLookupEdgeSrcDst() {} + + static void SetUpTestCase() {} + static void TearDownTestCase() {} + + virtual void SetUp() {} + virtual void TearDown() {} + + template + void run_current_test(std::tuple const& param) + { + auto [lookup_usecase, input_usecase] = param; + + raft::handle_t handle{}; + HighResTimer hr_timer{}; + + if (cugraph::test::g_perf) { + RAFT_CUDA_TRY(cudaDeviceSynchronize()); + hr_timer.start("Construct graph"); + } + + constexpr bool multi_gpu = false; + + bool test_weighted = true; + bool renumber = true; + bool drop_self_loops = false; + bool drop_multi_edges = false; + + auto [sg_graph, sg_edge_weights, sg_renumber_map] = + cugraph::test::construct_graph( + handle, input_usecase, test_weighted, renumber, drop_self_loops, drop_multi_edges); + + std::tie(sg_graph, sg_edge_weights, sg_renumber_map) = cugraph::symmetrize_graph( + handle, std::move(sg_graph), std::move(sg_edge_weights), std::move(sg_renumber_map), false); + + if (cugraph::test::g_perf) { + RAFT_CUDA_TRY(cudaDeviceSynchronize()); + hr_timer.stop(); + hr_timer.display_and_clear(std::cout); + } + + auto sg_graph_view = sg_graph.view(); + auto sg_edge_weight_view = + sg_edge_weights ? std::make_optional((*sg_edge_weights).view()) : std::nullopt; + + std::optional> edge_mask{std::nullopt}; + if (lookup_usecase.edge_masking) { + edge_mask = cugraph::test::generate::edge_property( + handle, sg_graph_view, 2); + // sg_graph_view.attach_edge_mask((*edge_mask).view()); + } + + int32_t nr_hash_bins = 6 + static_cast(sg_graph_view.number_of_vertices() / (1 << 10)); + + std::optional> edge_types{ + std::nullopt}; + edge_types = cugraph::test::generate::edge_property( + handle, sg_graph_view, nr_hash_bins); + + std::optional> edge_ids{std::nullopt}; + + edge_ids = cugraph::test::generate::edge_property( + handle, sg_graph_view, 1); + + auto edge_counts = (*edge_ids).view().edge_counts(); + + std::vector type_freqs(nr_hash_bins, 0); + std::mutex mtx[nr_hash_bins]; + + for (size_t ep_idx = 0; ep_idx < edge_counts.size(); ep_idx++) { + auto ep_types = + cugraph::test::to_host(handle, + raft::device_span( + (*edge_types).view().value_firsts()[ep_idx], edge_counts[ep_idx])); + + std::for_each(std::execution::par, ep_types.begin(), ep_types.end(), [&](int32_t et) { + std::lock_guard guard(mtx[et]); + type_freqs[et]++; + }); + + auto ep_ids = + cugraph::test::to_host(handle, + raft::device_span( + (*edge_ids).view().value_firsts()[ep_idx], edge_counts[ep_idx])); + } + + assert(std::reduce(type_freqs.cbegin(), type_freqs.cend()) == + std::reduce(edge_counts.cbegin(), edge_counts.cend())); + + auto d_type_freqs = cugraph::test::to_device(handle, type_freqs); + + std::vector distributed_type_offsets(nr_hash_bins); + + for (size_t i = 0; i < nr_hash_bins; i++) { + distributed_type_offsets[i] = type_freqs[i]; + } + + assert(std::reduce(distributed_type_offsets.cbegin(), distributed_type_offsets.cend()) == + sg_graph_view.compute_number_of_edges(handle)); + + auto number_of_local_edges = std::reduce(edge_counts.cbegin(), edge_counts.cend()); + + for (size_t ep_idx = 0; ep_idx < edge_counts.size(); ep_idx++) { + auto ep_types = + cugraph::test::to_host(handle, + raft::device_span( + (*edge_types).view().value_firsts()[ep_idx], edge_counts[ep_idx])); + + auto ep_ids = + cugraph::test::to_host(handle, + raft::device_span( + (*edge_ids).view().value_firsts()[ep_idx], edge_counts[ep_idx])); + + std::transform(ep_types.cbegin(), ep_types.cend(), ep_ids.begin(), [&](int32_t et) { + edge_t val = distributed_type_offsets[et]; + distributed_type_offsets[et]++; + return val; + }); + + raft::update_device((*edge_ids).mutable_view().value_firsts()[ep_idx], + ep_ids.data(), + ep_ids.size(), + handle.get_stream()); + } + + auto search_container = + cugraph::build_edge_id_and_type_to_src_dst_lookup_map( + handle, sg_graph_view, (*edge_ids).view(), (*edge_types).view()); + + if (lookup_usecase.check_correctness) { + rmm::device_uvector d_mg_srcs(0, handle.get_stream()); + rmm::device_uvector d_mg_dsts(0, handle.get_stream()); + + std::optional> d_mg_edge_ids{std::nullopt}; + std::optional> d_mg_edge_types{std::nullopt}; + + std::tie(d_mg_srcs, d_mg_dsts, std::ignore, d_mg_edge_ids, d_mg_edge_types) = + cugraph::decompress_to_edgelist( + handle, + sg_graph_view, + std::optional>{std::nullopt}, + std::make_optional((*edge_ids).view()), + std::make_optional((*edge_types).view()), + std::optional>{std::nullopt}); + + auto number_of_edges = sg_graph_view.compute_number_of_edges(handle); + + auto h_mg_edge_ids = cugraph::test::to_host(handle, d_mg_edge_ids); + auto h_mg_edge_types = cugraph::test::to_host(handle, d_mg_edge_types); + + auto h_srcs_expected = cugraph::test::to_host(handle, d_mg_srcs); + auto h_dsts_expected = cugraph::test::to_host(handle, d_mg_dsts); + + if (number_of_local_edges > 0) { + int nr_wrong_ids_or_types = (std::rand() % number_of_local_edges); + + for (int k = 0; k < nr_wrong_ids_or_types; k++) { + auto id_or_type = std::rand() % 2; + auto random_idx = std::rand() % number_of_local_edges; + if (id_or_type) + (*h_mg_edge_ids)[random_idx] = std::numeric_limits::max(); + else + (*h_mg_edge_types)[random_idx] = nr_hash_bins; + + h_srcs_expected[random_idx] = cugraph::invalid_vertex_id::value; + h_dsts_expected[random_idx] = cugraph::invalid_vertex_id::value; + } + } + + d_mg_edge_ids = cugraph::test::to_device(handle, h_mg_edge_ids); + d_mg_edge_types = cugraph::test::to_device(handle, h_mg_edge_types); + + auto [srcs, dsts] = + cugraph::cugraph_lookup_src_dst_from_edge_id_and_type( + handle, + search_container, + raft::device_span((*d_mg_edge_ids).begin(), (*d_mg_edge_ids).size()), + raft::device_span((*d_mg_edge_types).begin(), (*d_mg_edge_types).size())); + + auto h_srcs_results = cugraph::test::to_host(handle, srcs); + auto h_dsts_results = cugraph::test::to_host(handle, dsts); + + EXPECT_EQ(h_srcs_expected.size(), h_srcs_results.size()); + ASSERT_TRUE( + std::equal(h_srcs_expected.begin(), h_srcs_expected.end(), h_srcs_results.begin())); + + EXPECT_EQ(h_dsts_expected.size(), h_dsts_results.size()); + ASSERT_TRUE( + std::equal(h_dsts_expected.begin(), h_dsts_expected.end(), h_dsts_results.begin())); + } + } +}; + +using Tests_SGLookupEdgeSrcDst_File = Tests_SGLookupEdgeSrcDst; +using Tests_SGLookupEdgeSrcDst_Rmat = Tests_SGLookupEdgeSrcDst; + +TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +INSTANTIATE_TEST_SUITE_P( + file_test, + Tests_SGLookupEdgeSrcDst_File, + ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{false} + // , EdgeSrcDstLookup_UseCase{true} + ), + ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); + +INSTANTIATE_TEST_SUITE_P(rmat_small_test, + Tests_SGLookupEdgeSrcDst_Rmat, + ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{false} + // , EdgeSrcDstLookup_UseCase{true} + ), + ::testing::Values(cugraph::test::Rmat_Usecase( + 3, 3, 0.57, 0.19, 0.19, 0, true, false)))); + +INSTANTIATE_TEST_SUITE_P( + rmat_benchmark_test, /* note that scale & edge factor can be overridden in benchmarking (with + --gtest_filter to select only the rmat_benchmark_test with a specific + vertex & edge type combination) by command line arguments and do not + include more than one Rmat_Usecase that differ only in scale or edge + factor (to avoid running same benchmarks more than once) */ + Tests_SGLookupEdgeSrcDst_Rmat, + ::testing::Combine( + ::testing::Values(EdgeSrcDstLookup_UseCase{false, false} + // , EdgeSrcDstLookup_UseCase{true, false} + ), + ::testing::Values(cugraph::test::Rmat_Usecase(20, 32, 0.57, 0.19, 0.19, 0, false, false)))); + +CUGRAPH_TEST_PROGRAM_MAIN() diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp new file mode 100644 index 00000000000..8384926a357 --- /dev/null +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (c) 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. + * 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 governin_from_mtxg permissions and + * limitations under the License. + */ + +#include "utilities/base_fixture.hpp" +#include "utilities/conversion_utilities.hpp" +#include "utilities/device_comm_wrapper.hpp" +#include "utilities/mg_utilities.hpp" +#include "utilities/property_generator_utilities.hpp" +#include "utilities/test_graphs.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +struct EdgeSrcDstLookup_UseCase { + bool edge_masking{false}; + bool check_correctness{true}; +}; + +template +class Tests_MGLookupEdgeSrcDst + : public ::testing::TestWithParam> { + public: + Tests_MGLookupEdgeSrcDst() {} + + static void SetUpTestCase() { handle_ = cugraph::test::initialize_mg_handle(); } + static void TearDownTestCase() { handle_.reset(); } + + virtual void SetUp() {} + virtual void TearDown() {} + + template + void run_current_test(std::tuple const& param) + { + auto [lookup_usecase, input_usecase] = param; + + HighResTimer hr_timer{}; + + if (cugraph::test::g_perf) { + RAFT_CUDA_TRY(cudaDeviceSynchronize()); + handle_->get_comms().barrier(); + hr_timer.start("MG Construct graph"); + } + + constexpr bool multi_gpu = true; + + bool test_weighted = false; + bool renumber = true; + bool drop_self_loops = false; + bool drop_multi_edges = false; + + auto [mg_graph, mg_edge_weights, mg_renumber_map] = + cugraph::test::construct_graph( + *handle_, input_usecase, test_weighted, renumber, drop_self_loops, drop_multi_edges); + + std::tie(mg_graph, mg_edge_weights, mg_renumber_map) = cugraph::symmetrize_graph( + *handle_, + std::move(mg_graph), + std::move(mg_edge_weights), + mg_renumber_map ? std::optional>(std::move(*mg_renumber_map)) + : std::nullopt, + false); + + if (cugraph::test::g_perf) { + RAFT_CUDA_TRY(cudaDeviceSynchronize()); + handle_->get_comms().barrier(); + hr_timer.stop(); + hr_timer.display_and_clear(std::cout); + } + + auto mg_graph_view = mg_graph.view(); + auto mg_edge_weight_view = + mg_edge_weights ? std::make_optional((*mg_edge_weights).view()) : std::nullopt; + + std::optional> edge_mask{std::nullopt}; + if (lookup_usecase.edge_masking) { + edge_mask = cugraph::test::generate::edge_property( + *handle_, mg_graph_view, 2); + // mg_graph_view.attach_edge_mask((*edge_mask).view()); + } + + int32_t number_of_edge_types = + 6 + static_cast(mg_graph_view.number_of_vertices() / (1 << 10)); + + std::optional> edge_types{ + std::nullopt}; + edge_types = cugraph::test::generate::edge_property( + *handle_, mg_graph_view, number_of_edge_types); + + std::optional> edge_ids{std::nullopt}; + + edge_ids = cugraph::test::generate::edge_property( + *handle_, mg_graph_view, 1); + + auto edge_counts = (*edge_ids).view().edge_counts(); + + auto const comm_rank = (*handle_).get_comms().get_rank(); + auto const comm_size = (*handle_).get_comms().get_size(); + + std::vector type_freqs(number_of_edge_types, 0); + std::mutex mtx[number_of_edge_types]; + + for (size_t ep_idx = 0; ep_idx < edge_counts.size(); ep_idx++) { + auto ep_types = + cugraph::test::to_host(*handle_, + raft::device_span( + (*edge_types).view().value_firsts()[ep_idx], edge_counts[ep_idx])); + + std::for_each(std::execution::par, ep_types.begin(), ep_types.end(), [&](int32_t et) { + std::lock_guard guard(mtx[et]); + type_freqs[et]++; + }); + + auto ep_ids = + cugraph::test::to_host(*handle_, + raft::device_span( + (*edge_ids).view().value_firsts()[ep_idx], edge_counts[ep_idx])); + } + + assert(std::reduce(type_freqs.cbegin(), type_freqs.cend()) == + std::reduce(edge_counts.cbegin(), edge_counts.cend())); + + auto d_type_freqs = cugraph::test::to_device(*handle_, type_freqs); + d_type_freqs = + cugraph::test::device_allgatherv(*handle_, d_type_freqs.data(), d_type_freqs.size()); + type_freqs = cugraph::test::to_host(*handle_, d_type_freqs); + + std::vector distributed_type_offsets(comm_size * number_of_edge_types); + + for (size_t i = 0; i < number_of_edge_types; i++) { + for (size_t j = 0; j < comm_size; j++) { + distributed_type_offsets[j + comm_size * i] = type_freqs[number_of_edge_types * j + i]; + } + } + + // prefix sum for each type + for (size_t i = 0; i < number_of_edge_types; i++) { + auto start = distributed_type_offsets.begin() + i * comm_size; + std::exclusive_scan(start, start + comm_size, start, 0); + } + + assert(std::reduce(distributed_type_offsets.cbegin(), distributed_type_offsets.cend()) == + mg_graph_view.compute_number_of_edges(*handle_)); + + auto number_of_local_edges = std::reduce(edge_counts.cbegin(), edge_counts.cend()); + + for (size_t ep_idx = 0; ep_idx < edge_counts.size(); ep_idx++) { + auto ep_types = + cugraph::test::to_host(*handle_, + raft::device_span( + (*edge_types).view().value_firsts()[ep_idx], edge_counts[ep_idx])); + + auto ep_ids = + cugraph::test::to_host(*handle_, + raft::device_span( + (*edge_ids).view().value_firsts()[ep_idx], edge_counts[ep_idx])); + + std::transform(ep_types.cbegin(), ep_types.cend(), ep_ids.begin(), [&](int32_t et) { + edge_t val = distributed_type_offsets[(comm_size * et + comm_rank)]; + distributed_type_offsets[(comm_size * et + comm_rank)]++; + return val; + }); + + raft::update_device((*edge_ids).mutable_view().value_firsts()[ep_idx], + ep_ids.data(), + ep_ids.size(), + handle_->get_stream()); + } + + auto search_container = + cugraph::build_edge_id_and_type_to_src_dst_lookup_map( + *handle_, mg_graph_view, (*edge_ids).view(), (*edge_types).view()); + + if (lookup_usecase.check_correctness) { + rmm::device_uvector d_mg_srcs(0, handle_->get_stream()); + rmm::device_uvector d_mg_dsts(0, handle_->get_stream()); + + std::optional> d_mg_edge_ids{std::nullopt}; + std::optional> d_mg_edge_types{std::nullopt}; + + std::tie(d_mg_srcs, d_mg_dsts, std::ignore, d_mg_edge_ids, d_mg_edge_types) = + cugraph::decompress_to_edgelist( + *handle_, + mg_graph_view, + std::optional>{std::nullopt}, + std::make_optional((*edge_ids).view()), + std::make_optional((*edge_types).view()), + std::optional>{std::nullopt}); + + auto number_of_edges = mg_graph_view.compute_number_of_edges(*handle_); + + auto h_mg_edge_ids = cugraph::test::to_host(*handle_, d_mg_edge_ids); + auto h_mg_edge_types = cugraph::test::to_host(*handle_, d_mg_edge_types); + + auto h_srcs_expected = cugraph::test::to_host(*handle_, d_mg_srcs); + auto h_dsts_expected = cugraph::test::to_host(*handle_, d_mg_dsts); + + if (number_of_local_edges > 0) { + int nr_wrong_ids_or_types = (std::rand() % number_of_local_edges); + + for (int k = 0; k < nr_wrong_ids_or_types; k++) { + auto id_or_type = std::rand() % 2; + auto random_idx = std::rand() % number_of_local_edges; + if (id_or_type) + (*h_mg_edge_ids)[random_idx] = std::numeric_limits::max(); + else + (*h_mg_edge_types)[random_idx] = number_of_edge_types; + + h_srcs_expected[random_idx] = cugraph::invalid_vertex_id::value; + h_dsts_expected[random_idx] = cugraph::invalid_vertex_id::value; + } + } + + d_mg_edge_ids = cugraph::test::to_device(*handle_, h_mg_edge_ids); + d_mg_edge_types = cugraph::test::to_device(*handle_, h_mg_edge_types); + + auto [srcs, dsts] = + cugraph::cugraph_lookup_src_dst_from_edge_id_and_type( + *handle_, + search_container, + raft::device_span((*d_mg_edge_ids).begin(), (*d_mg_edge_ids).size()), + raft::device_span((*d_mg_edge_types).begin(), (*d_mg_edge_types).size())); + + auto h_srcs_results = cugraph::test::to_host(*handle_, srcs); + auto h_dsts_results = cugraph::test::to_host(*handle_, dsts); + + EXPECT_EQ(h_srcs_expected.size(), h_srcs_results.size()); + ASSERT_TRUE( + std::equal(h_srcs_expected.begin(), h_srcs_expected.end(), h_srcs_results.begin())); + + EXPECT_EQ(h_dsts_expected.size(), h_dsts_results.size()); + ASSERT_TRUE( + std::equal(h_dsts_expected.begin(), h_dsts_expected.end(), h_dsts_results.begin())); + } + } + + private: + static std::unique_ptr handle_; +}; + +template +std::unique_ptr Tests_MGLookupEdgeSrcDst::handle_ = nullptr; + +using Tests_MGLookupEdgeSrcDst_File = Tests_MGLookupEdgeSrcDst; +using Tests_MGLookupEdgeSrcDst_Rmat = Tests_MGLookupEdgeSrcDst; + +TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +INSTANTIATE_TEST_SUITE_P( + file_test, + Tests_MGLookupEdgeSrcDst_File, + ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{false} + // , EdgeSrcDstLookup_UseCase{true} + ), + ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); + +INSTANTIATE_TEST_SUITE_P(rmat_small_test, + Tests_MGLookupEdgeSrcDst_Rmat, + ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{false} + // , EdgeSrcDstLookup_UseCase{true} + ), + ::testing::Values(cugraph::test::Rmat_Usecase( + 3, 2, 0.57, 0.19, 0.19, 0, true, false)))); + +INSTANTIATE_TEST_SUITE_P( + rmat_benchmark_test, /* note that scale & edge factor can be overridden in benchmarking (with + --gtest_filter to select only the rmat_benchmark_test with a specific + vertex & edge type combination) by command line arguments and do not + include more than one Rmat_Usecase that differ only in scale or edge + factor (to avoid running same benchmarks more than once) */ + Tests_MGLookupEdgeSrcDst_Rmat, + ::testing::Combine( + ::testing::Values(EdgeSrcDstLookup_UseCase{false, false} + // , EdgeSrcDstLookup_UseCase{true, false} + ), + ::testing::Values(cugraph::test::Rmat_Usecase(5, 32, 0.57, 0.19, 0.19, 0, true, false)))); + +CUGRAPH_MG_TEST_PROGRAM_MAIN() From b1f494e41f02adf17e8602cc5cc0eb4fde1a8850 Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 02:13:12 +0200 Subject: [PATCH 02/26] fix linting --- cpp/src/lookup/lookup_src_dst.cu | 6 +++--- cpp/tests/CMakeLists.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/src/lookup/lookup_src_dst.cu b/cpp/src/lookup/lookup_src_dst.cu index 6d6e7719e71..807f4bd19be 100644 --- a/cpp/src/lookup/lookup_src_dst.cu +++ b/cpp/src/lookup/lookup_src_dst.cu @@ -627,9 +627,9 @@ EdgeTypeAndIdToSrcDstLookupContainerType create_edge_id_and_type_to_src_dst_look (*edgelist_types).end())), [key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ - comm_size, major_comm_size, minor_comm_size}] __device__(auto val) { - return key_func(thrust::get<2>(val)); - }, + comm_size, + major_comm_size, + minor_comm_size}] __device__(auto val) { return key_func(thrust::get<2>(val)); }, handle.get_stream()); } diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index b5c8b4bf038..2934536295a 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -496,7 +496,7 @@ ConfigureTest(EDGE_TRIANGLE_COUNT_TEST community/edge_triangle_count_test.cpp) ################################################################################################### # - EDGE SOURCE DESTINATION LOOKUP tests ---------------------------------------------------------- -ConfigureTestMG(LOOKUP_SRC_DST_TEST lookup/lookup_src_dst_test.cpp) +ConfigureTest(LOOKUP_SRC_DST_TEST lookup/lookup_src_dst_test.cpp) ################################################################################################### # - K-hop Neighbors tests ------------------------------------------------------------------------- From bc14f96ad6f3c8486ef227caefc00d538278a680 Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 02:17:43 +0200 Subject: [PATCH 03/26] clang-format --- cpp/src/lookup/lookup_src_dst.cu | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/lookup/lookup_src_dst.cu b/cpp/src/lookup/lookup_src_dst.cu index 807f4bd19be..dd711db0904 100644 --- a/cpp/src/lookup/lookup_src_dst.cu +++ b/cpp/src/lookup/lookup_src_dst.cu @@ -627,9 +627,9 @@ EdgeTypeAndIdToSrcDstLookupContainerType create_edge_id_and_type_to_src_dst_look (*edgelist_types).end())), [key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ - comm_size, - major_comm_size, - minor_comm_size}] __device__(auto val) { return key_func(thrust::get<2>(val)); }, + comm_size, + major_comm_size, + minor_comm_size}] __device__(auto val) { return key_func(thrust::get<2>(val)); }, handle.get_stream()); } From 28f4805b846acd9ba258633d74c5a42049c0465f Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 02:31:22 +0200 Subject: [PATCH 04/26] Add FIXME --- cpp/tests/lookup/lookup_src_dst_test.cpp | 31 ++++++++++++--------- cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 6 ++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp index 1272641c6ae..fae89572276 100644 --- a/cpp/tests/lookup/lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -98,12 +98,19 @@ class Tests_SGLookupEdgeSrcDst // sg_graph_view.attach_edge_mask((*edge_mask).view()); } - int32_t nr_hash_bins = 6 + static_cast(sg_graph_view.number_of_vertices() / (1 << 10)); + // + // FIXME: As the graph generator doesn't generate edge ids and types at the moment, generate + // edge ids and types for now and remove the code for generating edge ids and types from this + // file once the graph generator is updated to generate edge ids and types. + // + + int32_t number_of_edge_types = + 6 + static_cast(sg_graph_view.number_of_vertices() / (1 << 10)); std::optional> edge_types{ std::nullopt}; edge_types = cugraph::test::generate::edge_property( - handle, sg_graph_view, nr_hash_bins); + handle, sg_graph_view, number_of_edge_types); std::optional> edge_ids{std::nullopt}; @@ -112,8 +119,8 @@ class Tests_SGLookupEdgeSrcDst auto edge_counts = (*edge_ids).view().edge_counts(); - std::vector type_freqs(nr_hash_bins, 0); - std::mutex mtx[nr_hash_bins]; + std::vector type_freqs(number_of_edge_types, 0); + std::mutex mtx[number_of_edge_types]; for (size_t ep_idx = 0; ep_idx < edge_counts.size(); ep_idx++) { auto ep_types = @@ -137,14 +144,12 @@ class Tests_SGLookupEdgeSrcDst auto d_type_freqs = cugraph::test::to_device(handle, type_freqs); - std::vector distributed_type_offsets(nr_hash_bins); + std::vector type_offsets(number_of_edge_types); - for (size_t i = 0; i < nr_hash_bins; i++) { - distributed_type_offsets[i] = type_freqs[i]; - } + std::copy(type_freqs.begin(), type_freqs.end(), type_offsets.begin()) - assert(std::reduce(distributed_type_offsets.cbegin(), distributed_type_offsets.cend()) == - sg_graph_view.compute_number_of_edges(handle)); + assert(std::reduce(type_offsets.cbegin(), type_offsets.cend()) == + sg_graph_view.compute_number_of_edges(handle)); auto number_of_local_edges = std::reduce(edge_counts.cbegin(), edge_counts.cend()); @@ -160,8 +165,8 @@ class Tests_SGLookupEdgeSrcDst (*edge_ids).view().value_firsts()[ep_idx], edge_counts[ep_idx])); std::transform(ep_types.cbegin(), ep_types.cend(), ep_ids.begin(), [&](int32_t et) { - edge_t val = distributed_type_offsets[et]; - distributed_type_offsets[et]++; + edge_t val = type_offsets[et]; + type_offsets[et]++; return val; }); @@ -208,7 +213,7 @@ class Tests_SGLookupEdgeSrcDst if (id_or_type) (*h_mg_edge_ids)[random_idx] = std::numeric_limits::max(); else - (*h_mg_edge_types)[random_idx] = nr_hash_bins; + (*h_mg_edge_types)[random_idx] = number_of_edge_types; h_srcs_expected[random_idx] = cugraph::invalid_vertex_id::value; h_dsts_expected[random_idx] = cugraph::invalid_vertex_id::value; diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp index 8384926a357..629cd0e7b04 100644 --- a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -106,6 +106,12 @@ class Tests_MGLookupEdgeSrcDst // mg_graph_view.attach_edge_mask((*edge_mask).view()); } + // + // FIXME: As the graph generator doesn't generate edge ids and types at the moment, generate + // edge ids and types for now and remove the code for generating edge ids and types from this + // file once the graph generator is updated to generate edge ids and types. + // + int32_t number_of_edge_types = 6 + static_cast(mg_graph_view.number_of_vertices() / (1 << 10)); From 434c760d4e915313b23c9bb1a9e6d6926152fa41 Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 12:50:57 +0200 Subject: [PATCH 05/26] Add missing semicolon --- cpp/tests/lookup/lookup_src_dst_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp index fae89572276..9b1e0f6e0b7 100644 --- a/cpp/tests/lookup/lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -146,10 +146,10 @@ class Tests_SGLookupEdgeSrcDst std::vector type_offsets(number_of_edge_types); - std::copy(type_freqs.begin(), type_freqs.end(), type_offsets.begin()) + std::copy(type_freqs.begin(), type_freqs.end(), type_offsets.begin()); - assert(std::reduce(type_offsets.cbegin(), type_offsets.cend()) == - sg_graph_view.compute_number_of_edges(handle)); + assert(std::reduce(type_offsets.cbegin(), type_offsets.cend()) == + sg_graph_view.compute_number_of_edges(handle)); auto number_of_local_edges = std::reduce(edge_counts.cbegin(), edge_counts.cend()); From e81979780190773925a8bf8acf809d75dd4fafa5 Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 15:29:01 +0200 Subject: [PATCH 06/26] Restructure the files to conform to other algorithm implementation --- cpp/CMakeLists.txt | 4 +- cpp/include/cugraph/algorithms.hpp | 4 +- .../cugraph/src_dst_lookup_container.hpp | 20 +- ...kup_src_dst.cu => lookup_src_dst_impl.cuh} | 506 +++++++++++++----- cpp/src/lookup/lookup_src_dst_mg.cu | 88 +++ cpp/src/lookup/lookup_src_dst_sg.cu | 87 +++ cpp/src/lookup/src_dst_lookup_container.cu | 43 +- cpp/tests/lookup/lookup_src_dst_test.cpp | 2 +- cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 2 +- 9 files changed, 577 insertions(+), 179 deletions(-) rename cpp/src/lookup/{lookup_src_dst.cu => lookup_src_dst_impl.cuh} (68%) create mode 100644 cpp/src/lookup/lookup_src_dst_mg.cu create mode 100644 cpp/src/lookup/lookup_src_dst_sg.cu diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index e0a66562f30..63b174a190d 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -171,8 +171,8 @@ set(CUGRAPH_SOURCES src/utilities/shuffle_vertices.cu src/detail/permute_range.cu src/utilities/shuffle_vertex_pairs.cu - src/lookup/lookup_src_dst.cu - src/lookup/src_dst_lookup_container.cu + src/lookup/lookup_src_dst_sg.cu + src/lookup/lookup_src_dst_mg.cu src/detail/collect_local_vertex_values.cu src/detail/groupby_and_count.cu src/detail/collect_comm_wrapper.cu diff --git a/cpp/include/cugraph/algorithms.hpp b/cpp/include/cugraph/algorithms.hpp index c257ba7dd30..2fbefd3b6d4 100644 --- a/cpp/include/cugraph/algorithms.hpp +++ b/cpp/include/cugraph/algorithms.hpp @@ -2458,7 +2458,7 @@ build_edge_id_and_type_to_src_dst_lookup_map( */ template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( +lookup_src_dst_from_edge_id_and_type( raft::handle_t const& handle, search_container_t> const& search_container, @@ -2487,7 +2487,7 @@ cugraph_lookup_src_dst_from_edge_id_and_type( */ template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( +lookup_src_dst_from_edge_id_and_type( raft::handle_t const& handle, search_container_t> const& search_container, diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index d1c835413b1..bec8776c757 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -51,8 +51,8 @@ constexpr TupleType invalid_of_thrust_tuple_of_integral() template class search_container_t { template - struct impl; - std::unique_ptr> pimpl; + struct search_container_impl; + std::unique_ptr> pimpl; public: using edge_id_type = edge_id_t; @@ -77,16 +77,16 @@ class search_container_t { 0, rmm::cuda_stream_view{}))&& values_to_insert); std::optional(0, rmm::cuda_stream_view{}))> - lookup_src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup, - bool multi_gpu) const; + src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const; std::optional(0, rmm::cuda_stream_view{}))> - lookup_src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup, - bool multi_gpu) const; + src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const; void print() const; }; diff --git a/cpp/src/lookup/lookup_src_dst.cu b/cpp/src/lookup/lookup_src_dst_impl.cuh similarity index 68% rename from cpp/src/lookup/lookup_src_dst.cu rename to cpp/src/lookup/lookup_src_dst_impl.cuh index dd711db0904..6a2e17d3e27 100644 --- a/cpp/src/lookup/lookup_src_dst.cu +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -13,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "detail/graph_partition_utils.cuh" #include "prims/kv_store.cuh" #include "utilities/collect_comm.cuh" #include #include #include +#include #include #include #include @@ -26,6 +28,355 @@ #include namespace cugraph { + +template +template +struct search_container_t::search_container_impl { + private: + using container_t = + std::unordered_map>; + using store_t = typename container_t::mapped_type; + container_t edge_type_to_kv_store; + + public: + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + ~search_container_impl() {} + search_container_impl() {} + search_container_impl(raft::handle_t const& handle, + std::vector typs, + std::vector typ_freqs) + { + auto invalid_key = cugraph::invalid_vertex_id::value; + auto invalid_value = invalid_of_thrust_tuple_of_integral(); + + edge_type_to_kv_store = container_t{}; + edge_type_to_kv_store.reserve(typs.size()); + + for (size_t idx = 0; idx < typs.size(); idx++) { + auto typ = typs[idx]; + size_t store_capacity = typ_freqs[idx]; + + edge_type_to_kv_store.insert( + {typ, std::move(store_t(store_capacity, invalid_key, invalid_value, handle.get_stream()))}); + } + } + + void print() const + { + for (const auto& [key, map] : edge_type_to_kv_store) { + std::cout << "key: " << key << " size: " << map.size() << std::endl; + } + } + + void insert(raft::handle_t const& handle, + edge_type_t type, + raft::device_span edge_ids_to_insert, + decltype(cugraph::allocate_dataframe_buffer( + 0, rmm::cuda_stream_view{}))&& values_to_insert) + { + auto itr = edge_type_to_kv_store.find(type); + + if (itr != edge_type_to_kv_store.end()) { + assert(itr->first == type); + + itr->second.insert(edge_ids_to_insert.begin(), + edge_ids_to_insert.end(), + cugraph::get_dataframe_buffer_begin(values_to_insert), + handle.get_stream()); + + } else { + assert(false); + } + } + + std::optional(0, rmm::cuda_stream_view{}))> + src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const + { + using store_t = typename container_t::mapped_type; + const store_t* kv_store_object{nullptr}; + + auto value_buffer = cugraph::allocate_dataframe_buffer(0, handle.get_stream()); + auto itr = edge_type_to_kv_store.find(edge_type_to_lookup); + + if (itr != edge_type_to_kv_store.end()) { + assert(edge_type_to_lookup == itr->first); + kv_store_object = &(itr->second); + + } else { + cugraph::resize_dataframe_buffer( + value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); + + auto invalid_value = invalid_of_thrust_tuple_of_integral(); + // Mark with invalid here + thrust::copy(handle.get_thrust_policy(), + thrust::make_constant_iterator(invalid_value), + thrust::make_constant_iterator(invalid_value) + edge_ids_to_lookup.size(), + cugraph::get_dataframe_buffer_begin(value_buffer)); + + return std::make_optional(std::move(value_buffer)); + } + + if (multi_gpu) { + auto& comm = handle.get_comms(); + auto const comm_size = comm.get_size(); + auto& major_comm = handle.get_subcomm(cugraph::partition_manager::major_comm_name()); + auto const major_comm_size = major_comm.get_size(); + auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); + auto const minor_comm_size = minor_comm.get_size(); + + auto key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ + comm_size, major_comm_size, minor_comm_size}; + + value_buffer = cugraph::collect_values_for_keys(handle, + kv_store_object->view(), + edge_ids_to_lookup.begin(), + edge_ids_to_lookup.end(), + key_func); + + } else { + cugraph::resize_dataframe_buffer( + value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); + + kv_store_object->view().find(edge_ids_to_lookup.begin(), + edge_ids_to_lookup.end(), + cugraph::get_dataframe_buffer_begin(value_buffer), + handle.get_stream()); + } + + return std::make_optional(std::move(value_buffer)); + } + + std::optional(0, rmm::cuda_stream_view{}))> + src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const + { + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + + assert(edge_ids_to_lookup.size() == edge_types_to_lookup.size()); + + rmm::device_uvector tmp_edge_ids_to_lookup(edge_ids_to_lookup.size(), + handle.get_stream()); + + rmm::device_uvector tmp_edge_types_to_lookup(edge_types_to_lookup.size(), + handle.get_stream()); + + rmm::device_uvector original_idxs(edge_ids_to_lookup.size(), handle.get_stream()); + + thrust::sequence( + handle.get_thrust_policy(), original_idxs.begin(), original_idxs.end(), edge_id_t{0}); + + thrust::copy(handle.get_thrust_policy(), + edge_ids_to_lookup.begin(), + edge_ids_to_lookup.end(), + tmp_edge_ids_to_lookup.begin()); + + thrust::copy(handle.get_thrust_policy(), + edge_types_to_lookup.begin(), + edge_types_to_lookup.end(), + tmp_edge_types_to_lookup.begin()); + + thrust::sort_by_key(handle.get_thrust_policy(), + tmp_edge_types_to_lookup.begin(), + tmp_edge_types_to_lookup.end(), + thrust::make_zip_iterator(thrust::make_tuple(tmp_edge_ids_to_lookup.begin(), + original_idxs.begin()))); + + auto nr_uniqe_edge_types_to_lookup = thrust::count_if( + handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator(tmp_edge_types_to_lookup.size()), + detail::is_first_in_run_t{tmp_edge_types_to_lookup.data()}); + + rmm::device_uvector unique_types(nr_uniqe_edge_types_to_lookup, + handle.get_stream()); + rmm::device_uvector type_offsets(nr_uniqe_edge_types_to_lookup + 1, + handle.get_stream()); + + thrust::fill( + handle.get_thrust_policy(), type_offsets.begin(), type_offsets.end(), edge_id_t{0}); + + thrust::reduce_by_key(handle.get_thrust_policy(), + tmp_edge_types_to_lookup.begin(), + tmp_edge_types_to_lookup.end(), + thrust::make_constant_iterator(size_t{1}), + unique_types.begin(), + type_offsets.begin()); + + thrust::exclusive_scan(handle.get_thrust_policy(), + type_offsets.begin(), + type_offsets.end(), + type_offsets.begin(), + size_t{0}); + + std::vector h_unique_types(unique_types.size()); + std::vector h_type_offsets(type_offsets.size()); + + raft::update_host( + h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); + + raft::update_host( + h_type_offsets.data(), type_offsets.data(), type_offsets.size(), handle.get_stream()); + + std::unordered_map typ_to_local_idx_map{}; + + RAFT_CUDA_TRY(cudaDeviceSynchronize()); + + for (size_t idx = 0; idx < h_unique_types.size(); idx++) { + typ_to_local_idx_map[h_unique_types[idx]] = idx; + } + + auto output_value_buffer = + cugraph::allocate_dataframe_buffer(edge_ids_to_lookup.size(), handle.get_stream()); + auto invalid_value = invalid_of_thrust_tuple_of_integral(); + thrust::fill(handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin(output_value_buffer), + cugraph::get_dataframe_buffer_begin(output_value_buffer), + invalid_value); + + if (multi_gpu) { + auto& comm = handle.get_comms(); + auto rx_counts = host_scalar_allgather(comm, unique_types.size(), handle.get_stream()); + std::vector rx_displacements(rx_counts.size()); + std::exclusive_scan(rx_counts.begin(), rx_counts.end(), rx_displacements.begin(), size_t{0}); + rmm::device_uvector rx_unique_types(rx_displacements.back() + rx_counts.back(), + handle.get_stream()); + + device_allgatherv(comm, + unique_types.begin(), + rx_unique_types.begin(), + rx_counts, + rx_displacements, + handle.get_stream()); + unique_types = std::move(rx_unique_types); + + thrust::sort(handle.get_thrust_policy(), unique_types.begin(), unique_types.end()); + + unique_types.resize( + thrust::distance( + unique_types.begin(), + thrust::unique(handle.get_thrust_policy(), unique_types.begin(), unique_types.end())), + handle.get_stream()); + } + + h_unique_types.resize(unique_types.size()); + raft::update_host( + h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); + + for (size_t idx = 0; idx < h_unique_types.size(); idx++) { + auto typ = h_unique_types[idx]; + + auto start_ptr = tmp_edge_ids_to_lookup.begin(); + size_t span_size = 0; + + if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { + auto xx = typ_to_local_idx_map[typ]; + + start_ptr = tmp_edge_ids_to_lookup.begin() + h_type_offsets[xx]; + span_size = h_type_offsets[xx + 1] - h_type_offsets[xx]; + } + + auto optional_value_buffer = src_dst_from_edge_id_and_type( + handle, raft::device_span{start_ptr, span_size}, typ, multi_gpu); + + if (optional_value_buffer.has_value()) { + if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { + thrust::copy(handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), + cugraph::get_dataframe_buffer_end((*optional_value_buffer)), + cugraph::get_dataframe_buffer_begin(output_value_buffer) + + h_type_offsets[typ_to_local_idx_map[typ]]); + } + } + } + + thrust::sort_by_key(handle.get_thrust_policy(), + original_idxs.begin(), + original_idxs.end(), + cugraph::get_dataframe_buffer_begin(output_value_buffer)); + + return std::make_optional(std::move(output_value_buffer)); + } +}; + +template +search_container_t::~search_container_t() +{ + pimpl.reset(); +} + +template +search_container_t::search_container_t() + : pimpl{std::make_unique>()} +{ +} + +template +search_container_t::search_container_t( + raft::handle_t const& handle, std::vector typs, std::vector typ_freqs) + : pimpl{std::make_unique>( + handle, typs, typ_freqs)} +{ +} + +template +search_container_t::search_container_t(const search_container_t&) +{ +} + +template +void search_container_t::insert( + raft::handle_t const& handle, + edge_type_t type, + raft::device_span edge_ids_to_insert, + decltype(cugraph::allocate_dataframe_buffer(0, + rmm::cuda_stream_view{}))&& values_to_insert) +{ + pimpl->insert(handle, type, edge_ids_to_insert, std::move(values_to_insert)); +} + +template +std::optional(0, rmm::cuda_stream_view{}))> +search_container_t::src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const +{ + return pimpl->src_dst_from_edge_id_and_type( + handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); +} + +template +std::optional(0, rmm::cuda_stream_view{}))> +search_container_t::src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const +{ + return pimpl->src_dst_from_edge_id_and_type( + handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); +} + +template +void search_container_t::print() const +{ + pimpl->print(); +} + namespace detail { template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( +lookup_src_dst_from_edge_id_and_type( raft::handle_t const& handle, EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, raft::device_span edge_ids_to_lookup, @@ -63,7 +414,7 @@ cugraph_lookup_src_dst_from_edge_id_and_type( thrust::fill( handle.get_thrust_policy(), output_dsts.begin(), output_dsts.end(), invalid_vertex_id); - auto optional_value_buffer = search_container.lookup_src_dst_from_edge_id_and_type( + auto optional_value_buffer = search_container.src_dst_from_edge_id_and_type( handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); if (optional_value_buffer.has_value()) { @@ -82,7 +433,7 @@ template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( +lookup_src_dst_from_edge_id_and_type( raft::handle_t const& handle, EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, raft::device_span edge_ids_to_lookup, @@ -114,7 +465,7 @@ cugraph_lookup_src_dst_from_edge_id_and_type( thrust::fill( handle.get_thrust_policy(), output_dsts.begin(), output_dsts.end(), invalid_vertex_id); - auto optional_value_buffer = search_container.lookup_src_dst_from_edge_id_and_type( + auto optional_value_buffer = search_container.src_dst_from_edge_id_and_type( handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); if (optional_value_buffer.has_value()) { @@ -131,7 +482,7 @@ template -EdgeTypeAndIdToSrcDstLookupContainerType create_edge_id_and_type_to_src_dst_lookup_map( +EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, GraphViewType const& graph_view, EdgeIdInputWrapper edge_id_view, @@ -716,7 +1067,7 @@ EdgeTypeAndIdToSrcDstLookupContainerType create_edge_id_and_type_to_src_dst_look template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( +lookup_src_dst_from_edge_id_and_type( raft::handle_t const& handle, search_container_t> const& search_container, @@ -725,13 +1076,13 @@ cugraph_lookup_src_dst_from_edge_id_and_type( { using m_t = search_container_t>; return detail:: - cugraph_lookup_src_dst_from_edge_id_and_type( + lookup_src_dst_from_edge_id_and_type( handle, search_container, edge_ids_to_lookup, edge_type_to_lookup); } template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( +lookup_src_dst_from_edge_id_and_type( raft::handle_t const& handle, search_container_t> const& search_container, @@ -740,7 +1091,7 @@ cugraph_lookup_src_dst_from_edge_id_and_type( { using m_t = search_container_t>; return detail:: - cugraph_lookup_src_dst_from_edge_id_and_type( + lookup_src_dst_from_edge_id_and_type( handle, search_container, edge_ids_to_lookup, edge_types_to_lookup); } @@ -755,139 +1106,10 @@ build_edge_id_and_type_to_src_dst_lookup_map( using graph_view_t = graph_view_t; using return_t = search_container_t>; - return detail::create_edge_id_and_type_to_src_dst_lookup_map( + return detail::build_edge_id_and_type_to_src_dst_lookup_map( handle, graph_view, edge_id_view, edge_type_view); } - -using edge_type_t = int32_t; - -template search_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( - raft::handle_t const& handle, - graph_view_t const& graph_view, - edge_property_view_t edge_id_view, - edge_property_view_t edge_type_view); - -template search_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( - raft::handle_t const& handle, - graph_view_t const& graph_view, - edge_property_view_t edge_id_view, - edge_property_view_t edge_type_view); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - int32_t const edge_type_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup); - -template search_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( - raft::handle_t const& handle, - graph_view_t const& graph_view, - edge_property_view_t edge_id_view, - edge_property_view_t edge_type_view); - -template search_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( - raft::handle_t const& handle, - graph_view_t const& graph_view, - edge_property_view_t edge_id_view, - edge_property_view_t edge_type_view); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - int32_t edge_type_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - int32_t edge_type_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup); - -template search_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( - raft::handle_t const& handle, - graph_view_t const& graph_view, - edge_property_view_t edge_id_view, - edge_property_view_t edge_type_view); - -template search_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( - raft::handle_t const& handle, - graph_view_t const& graph_view, - edge_property_view_t edge_id_view, - edge_property_view_t edge_type_view); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - int32_t edge_type_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - int32_t edge_type_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup); - -template std::tuple, rmm::device_uvector> -cugraph_lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& search_container, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup); - } // namespace cugraph diff --git a/cpp/src/lookup/lookup_src_dst_mg.cu b/cpp/src/lookup/lookup_src_dst_mg.cu new file mode 100644 index 00000000000..3eec8d8cc8c --- /dev/null +++ b/cpp/src/lookup/lookup_src_dst_mg.cu @@ -0,0 +1,88 @@ +/* + * Copyright (c) 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. + * 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. + */ + +#include "lookup/lookup_src_dst_impl.cuh" + +namespace cugraph { + +template class search_container_t>; +template class search_container_t>; +template class search_container_t>; + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +} // namespace cugraph diff --git a/cpp/src/lookup/lookup_src_dst_sg.cu b/cpp/src/lookup/lookup_src_dst_sg.cu new file mode 100644 index 00000000000..1ded6b740f1 --- /dev/null +++ b/cpp/src/lookup/lookup_src_dst_sg.cu @@ -0,0 +1,87 @@ +/* + * Copyright (c) 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. + * 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. + */ + +#include "lookup/lookup_src_dst_impl.cuh" + +namespace cugraph { + +template class search_container_t>; +template class search_container_t>; +template class search_container_t>; + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t const edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +template search_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + int32_t edge_type_to_lookup); +template std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + search_container_t> const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); + +} // namespace cugraph diff --git a/cpp/src/lookup/src_dst_lookup_container.cu b/cpp/src/lookup/src_dst_lookup_container.cu index f427509ddad..31f9db8af4a 100644 --- a/cpp/src/lookup/src_dst_lookup_container.cu +++ b/cpp/src/lookup/src_dst_lookup_container.cu @@ -26,7 +26,7 @@ namespace cugraph { template template -struct search_container_t::impl { +struct search_container_t::search_container_impl { private: using container_t = std::unordered_map::impl { static_assert(std::is_same_v); static_assert(std::is_same_v); - ~impl() {} - impl() {} - impl(raft::handle_t const& handle, - std::vector typs, - std::vector typ_freqs) + ~search_container_impl() {} + search_container_impl() {} + search_container_impl(raft::handle_t const& handle, + std::vector typs, + std::vector typ_freqs) { auto invalid_key = cugraph::invalid_vertex_id::value; auto invalid_value = invalid_of_thrust_tuple_of_integral(); @@ -92,10 +92,10 @@ struct search_container_t::impl { } std::optional(0, rmm::cuda_stream_view{}))> - lookup_src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup, - bool multi_gpu) const + src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const { using store_t = typename container_t::mapped_type; const store_t* kv_store_object{nullptr}; @@ -152,10 +152,10 @@ struct search_container_t::impl { } std::optional(0, rmm::cuda_stream_view{}))> - lookup_src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup, - bool multi_gpu) const + src_dst_from_edge_id_and_type(raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const { static_assert(std::is_integral_v); static_assert(std::is_integral_v); @@ -283,7 +283,7 @@ struct search_container_t::impl { span_size = h_type_offsets[xx + 1] - h_type_offsets[xx]; } - auto optional_value_buffer = lookup_src_dst_from_edge_id_and_type( + auto optional_value_buffer = src_dst_from_edge_id_and_type( handle, raft::device_span{start_ptr, span_size}, typ, multi_gpu); if (optional_value_buffer.has_value()) { @@ -314,14 +314,15 @@ search_container_t::~search_container_t() template search_container_t::search_container_t() - : pimpl{std::make_unique>()} + : pimpl{std::make_unique>()} { } template search_container_t::search_container_t( raft::handle_t const& handle, std::vector typs, std::vector typ_freqs) - : pimpl{std::make_unique>(handle, typs, typ_freqs)} + : pimpl{std::make_unique>( + handle, typs, typ_freqs)} { } @@ -343,25 +344,25 @@ void search_container_t::insert( template std::optional(0, rmm::cuda_stream_view{}))> -search_container_t::lookup_src_dst_from_edge_id_and_type( +search_container_t::src_dst_from_edge_id_and_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup, bool multi_gpu) const { - return pimpl->lookup_src_dst_from_edge_id_and_type( + return pimpl->src_dst_from_edge_id_and_type( handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); } template std::optional(0, rmm::cuda_stream_view{}))> -search_container_t::lookup_src_dst_from_edge_id_and_type( +search_container_t::src_dst_from_edge_id_and_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup, bool multi_gpu) const { - return pimpl->lookup_src_dst_from_edge_id_and_type( + return pimpl->src_dst_from_edge_id_and_type( handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); } diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp index 9b1e0f6e0b7..4316dd2f1ce 100644 --- a/cpp/tests/lookup/lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -224,7 +224,7 @@ class Tests_SGLookupEdgeSrcDst d_mg_edge_types = cugraph::test::to_device(handle, h_mg_edge_types); auto [srcs, dsts] = - cugraph::cugraph_lookup_src_dst_from_edge_id_and_type( + cugraph::lookup_src_dst_from_edge_id_and_type( handle, search_container, raft::device_span((*d_mg_edge_ids).begin(), (*d_mg_edge_ids).size()), diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp index 629cd0e7b04..10a24d075d8 100644 --- a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -248,7 +248,7 @@ class Tests_MGLookupEdgeSrcDst d_mg_edge_types = cugraph::test::to_device(*handle_, h_mg_edge_types); auto [srcs, dsts] = - cugraph::cugraph_lookup_src_dst_from_edge_id_and_type( + cugraph::lookup_src_dst_from_edge_id_and_type( *handle_, search_container, raft::device_span((*d_mg_edge_ids).begin(), (*d_mg_edge_ids).size()), From 367e2a57997993a1cd7f9623bc9348fa706f9ef1 Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 16:50:18 +0200 Subject: [PATCH 07/26] Remove unused function --- cpp/include/cugraph/src_dst_lookup_container.hpp | 1 - cpp/src/lookup/lookup_src_dst_impl.cuh | 13 ------------- cpp/src/lookup/src_dst_lookup_container.cu | 13 ------------- 3 files changed, 27 deletions(-) diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index bec8776c757..5f05067b11b 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -87,7 +87,6 @@ class search_container_t { raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup, bool multi_gpu) const; - void print() const; }; } // namespace cugraph diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index 6a2e17d3e27..266ecabd0c1 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -68,13 +68,6 @@ struct search_container_t::search_container_imp } } - void print() const - { - for (const auto& [key, map] : edge_type_to_kv_store) { - std::cout << "key: " << key << " size: " << map.size() << std::endl; - } - } - void insert(raft::handle_t const& handle, edge_type_t type, raft::device_span edge_ids_to_insert, @@ -371,12 +364,6 @@ search_container_t::src_dst_from_edge_id_and_ty handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); } -template -void search_container_t::print() const -{ - pimpl->print(); -} - namespace detail { template ::search_container_imp } } - void print() const - { - for (const auto& [key, map] : edge_type_to_kv_store) { - std::cout << "key: " << key << " size: " << map.size() << std::endl; - } - } - void insert(raft::handle_t const& handle, edge_type_t type, raft::device_span edge_ids_to_insert, @@ -366,12 +359,6 @@ search_container_t::src_dst_from_edge_id_and_ty handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); } -template -void search_container_t::print() const -{ - pimpl->print(); -} - template class search_container_t>; template class search_container_t>; template class search_container_t>; From e36a5a8bcab04f1abc5e25584a46ffe99e9e737e Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 16:51:58 +0200 Subject: [PATCH 08/26] Remove unused file --- cpp/src/lookup/src_dst_lookup_container.cu | 366 --------------------- 1 file changed, 366 deletions(-) delete mode 100644 cpp/src/lookup/src_dst_lookup_container.cu diff --git a/cpp/src/lookup/src_dst_lookup_container.cu b/cpp/src/lookup/src_dst_lookup_container.cu deleted file mode 100644 index 15843bde25e..00000000000 --- a/cpp/src/lookup/src_dst_lookup_container.cu +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 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. - * 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. - */ -#include "detail/graph_partition_utils.cuh" -#include "prims/kv_store.cuh" -#include "utilities/collect_comm.cuh" - -#include -#include -#include -#include - -namespace cugraph { - -template -template -struct search_container_t::search_container_impl { - private: - using container_t = - std::unordered_map>; - using store_t = typename container_t::mapped_type; - container_t edge_type_to_kv_store; - - public: - static_assert(std::is_integral_v); - static_assert(std::is_integral_v); - - static_assert(std::is_same_v); - static_assert(std::is_same_v); - static_assert(std::is_same_v); - - ~search_container_impl() {} - search_container_impl() {} - search_container_impl(raft::handle_t const& handle, - std::vector typs, - std::vector typ_freqs) - { - auto invalid_key = cugraph::invalid_vertex_id::value; - auto invalid_value = invalid_of_thrust_tuple_of_integral(); - - edge_type_to_kv_store = container_t{}; - edge_type_to_kv_store.reserve(typs.size()); - - for (size_t idx = 0; idx < typs.size(); idx++) { - auto typ = typs[idx]; - size_t store_capacity = typ_freqs[idx]; - - edge_type_to_kv_store.insert( - {typ, std::move(store_t(store_capacity, invalid_key, invalid_value, handle.get_stream()))}); - } - } - - void insert(raft::handle_t const& handle, - edge_type_t type, - raft::device_span edge_ids_to_insert, - decltype(cugraph::allocate_dataframe_buffer( - 0, rmm::cuda_stream_view{}))&& values_to_insert) - { - auto itr = edge_type_to_kv_store.find(type); - - if (itr != edge_type_to_kv_store.end()) { - assert(itr->first == type); - - itr->second.insert(edge_ids_to_insert.begin(), - edge_ids_to_insert.end(), - cugraph::get_dataframe_buffer_begin(values_to_insert), - handle.get_stream()); - - } else { - assert(false); - } - } - - std::optional(0, rmm::cuda_stream_view{}))> - src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup, - bool multi_gpu) const - { - using store_t = typename container_t::mapped_type; - const store_t* kv_store_object{nullptr}; - - auto value_buffer = cugraph::allocate_dataframe_buffer(0, handle.get_stream()); - auto itr = edge_type_to_kv_store.find(edge_type_to_lookup); - - if (itr != edge_type_to_kv_store.end()) { - assert(edge_type_to_lookup == itr->first); - kv_store_object = &(itr->second); - - } else { - cugraph::resize_dataframe_buffer( - value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); - - auto invalid_value = invalid_of_thrust_tuple_of_integral(); - // Mark with invalid here - thrust::copy(handle.get_thrust_policy(), - thrust::make_constant_iterator(invalid_value), - thrust::make_constant_iterator(invalid_value) + edge_ids_to_lookup.size(), - cugraph::get_dataframe_buffer_begin(value_buffer)); - - return std::make_optional(std::move(value_buffer)); - } - - if (multi_gpu) { - auto& comm = handle.get_comms(); - auto const comm_size = comm.get_size(); - auto& major_comm = handle.get_subcomm(cugraph::partition_manager::major_comm_name()); - auto const major_comm_size = major_comm.get_size(); - auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); - auto const minor_comm_size = minor_comm.get_size(); - - auto key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ - comm_size, major_comm_size, minor_comm_size}; - - value_buffer = cugraph::collect_values_for_keys(handle, - kv_store_object->view(), - edge_ids_to_lookup.begin(), - edge_ids_to_lookup.end(), - key_func); - - } else { - cugraph::resize_dataframe_buffer( - value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); - - kv_store_object->view().find(edge_ids_to_lookup.begin(), - edge_ids_to_lookup.end(), - cugraph::get_dataframe_buffer_begin(value_buffer), - handle.get_stream()); - } - - return std::make_optional(std::move(value_buffer)); - } - - std::optional(0, rmm::cuda_stream_view{}))> - src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup, - bool multi_gpu) const - { - static_assert(std::is_integral_v); - static_assert(std::is_integral_v); - - assert(edge_ids_to_lookup.size() == edge_types_to_lookup.size()); - - rmm::device_uvector tmp_edge_ids_to_lookup(edge_ids_to_lookup.size(), - handle.get_stream()); - - rmm::device_uvector tmp_edge_types_to_lookup(edge_types_to_lookup.size(), - handle.get_stream()); - - rmm::device_uvector original_idxs(edge_ids_to_lookup.size(), handle.get_stream()); - - thrust::sequence( - handle.get_thrust_policy(), original_idxs.begin(), original_idxs.end(), edge_id_t{0}); - - thrust::copy(handle.get_thrust_policy(), - edge_ids_to_lookup.begin(), - edge_ids_to_lookup.end(), - tmp_edge_ids_to_lookup.begin()); - - thrust::copy(handle.get_thrust_policy(), - edge_types_to_lookup.begin(), - edge_types_to_lookup.end(), - tmp_edge_types_to_lookup.begin()); - - thrust::sort_by_key(handle.get_thrust_policy(), - tmp_edge_types_to_lookup.begin(), - tmp_edge_types_to_lookup.end(), - thrust::make_zip_iterator(thrust::make_tuple(tmp_edge_ids_to_lookup.begin(), - original_idxs.begin()))); - - auto nr_uniqe_edge_types_to_lookup = thrust::count_if( - handle.get_thrust_policy(), - thrust::make_counting_iterator(size_t{0}), - thrust::make_counting_iterator(tmp_edge_types_to_lookup.size()), - detail::is_first_in_run_t{tmp_edge_types_to_lookup.data()}); - - rmm::device_uvector unique_types(nr_uniqe_edge_types_to_lookup, - handle.get_stream()); - rmm::device_uvector type_offsets(nr_uniqe_edge_types_to_lookup + 1, - handle.get_stream()); - - thrust::fill( - handle.get_thrust_policy(), type_offsets.begin(), type_offsets.end(), edge_id_t{0}); - - thrust::reduce_by_key(handle.get_thrust_policy(), - tmp_edge_types_to_lookup.begin(), - tmp_edge_types_to_lookup.end(), - thrust::make_constant_iterator(size_t{1}), - unique_types.begin(), - type_offsets.begin()); - - thrust::exclusive_scan(handle.get_thrust_policy(), - type_offsets.begin(), - type_offsets.end(), - type_offsets.begin(), - size_t{0}); - - std::vector h_unique_types(unique_types.size()); - std::vector h_type_offsets(type_offsets.size()); - - raft::update_host( - h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); - - raft::update_host( - h_type_offsets.data(), type_offsets.data(), type_offsets.size(), handle.get_stream()); - - std::unordered_map typ_to_local_idx_map{}; - - RAFT_CUDA_TRY(cudaDeviceSynchronize()); - - for (size_t idx = 0; idx < h_unique_types.size(); idx++) { - typ_to_local_idx_map[h_unique_types[idx]] = idx; - } - - auto output_value_buffer = - cugraph::allocate_dataframe_buffer(edge_ids_to_lookup.size(), handle.get_stream()); - auto invalid_value = invalid_of_thrust_tuple_of_integral(); - thrust::fill(handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin(output_value_buffer), - cugraph::get_dataframe_buffer_begin(output_value_buffer), - invalid_value); - - if (multi_gpu) { - auto& comm = handle.get_comms(); - auto rx_counts = host_scalar_allgather(comm, unique_types.size(), handle.get_stream()); - std::vector rx_displacements(rx_counts.size()); - std::exclusive_scan(rx_counts.begin(), rx_counts.end(), rx_displacements.begin(), size_t{0}); - rmm::device_uvector rx_unique_types(rx_displacements.back() + rx_counts.back(), - handle.get_stream()); - - device_allgatherv(comm, - unique_types.begin(), - rx_unique_types.begin(), - rx_counts, - rx_displacements, - handle.get_stream()); - unique_types = std::move(rx_unique_types); - - thrust::sort(handle.get_thrust_policy(), unique_types.begin(), unique_types.end()); - - unique_types.resize( - thrust::distance( - unique_types.begin(), - thrust::unique(handle.get_thrust_policy(), unique_types.begin(), unique_types.end())), - handle.get_stream()); - } - - h_unique_types.resize(unique_types.size()); - raft::update_host( - h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); - - for (size_t idx = 0; idx < h_unique_types.size(); idx++) { - auto typ = h_unique_types[idx]; - - auto start_ptr = tmp_edge_ids_to_lookup.begin(); - size_t span_size = 0; - - if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { - auto xx = typ_to_local_idx_map[typ]; - - start_ptr = tmp_edge_ids_to_lookup.begin() + h_type_offsets[xx]; - span_size = h_type_offsets[xx + 1] - h_type_offsets[xx]; - } - - auto optional_value_buffer = src_dst_from_edge_id_and_type( - handle, raft::device_span{start_ptr, span_size}, typ, multi_gpu); - - if (optional_value_buffer.has_value()) { - if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { - thrust::copy(handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), - cugraph::get_dataframe_buffer_end((*optional_value_buffer)), - cugraph::get_dataframe_buffer_begin(output_value_buffer) + - h_type_offsets[typ_to_local_idx_map[typ]]); - } - } - } - - thrust::sort_by_key(handle.get_thrust_policy(), - original_idxs.begin(), - original_idxs.end(), - cugraph::get_dataframe_buffer_begin(output_value_buffer)); - - return std::make_optional(std::move(output_value_buffer)); - } -}; - -template -search_container_t::~search_container_t() -{ - pimpl.reset(); -} - -template -search_container_t::search_container_t() - : pimpl{std::make_unique>()} -{ -} - -template -search_container_t::search_container_t( - raft::handle_t const& handle, std::vector typs, std::vector typ_freqs) - : pimpl{std::make_unique>( - handle, typs, typ_freqs)} -{ -} - -template -search_container_t::search_container_t(const search_container_t&) -{ -} - -template -void search_container_t::insert( - raft::handle_t const& handle, - edge_type_t type, - raft::device_span edge_ids_to_insert, - decltype(cugraph::allocate_dataframe_buffer(0, - rmm::cuda_stream_view{}))&& values_to_insert) -{ - pimpl->insert(handle, type, edge_ids_to_insert, std::move(values_to_insert)); -} - -template -std::optional(0, rmm::cuda_stream_view{}))> -search_container_t::src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup, - bool multi_gpu) const -{ - return pimpl->src_dst_from_edge_id_and_type( - handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); -} - -template -std::optional(0, rmm::cuda_stream_view{}))> -search_container_t::src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup, - bool multi_gpu) const -{ - return pimpl->src_dst_from_edge_id_and_type( - handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); -} - -template class search_container_t>; -template class search_container_t>; -template class search_container_t>; - -} // namespace cugraph From 222a1e261019973019584c84cc3c58b53451fe0c Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 17:56:42 +0200 Subject: [PATCH 09/26] Rearrange functions in a file --- cpp/src/lookup/lookup_src_dst_impl.cuh | 210 +++++++++++-------------- 1 file changed, 92 insertions(+), 118 deletions(-) diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index 266ecabd0c1..82a91d87336 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -32,14 +32,6 @@ namespace cugraph { template template struct search_container_t::search_container_impl { - private: - using container_t = - std::unordered_map>; - using store_t = typename container_t::mapped_type; - container_t edge_type_to_kv_store; - - public: static_assert(std::is_integral_v); static_assert(std::is_integral_v); @@ -110,7 +102,6 @@ struct search_container_t::search_container_imp value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); auto invalid_value = invalid_of_thrust_tuple_of_integral(); - // Mark with invalid here thrust::copy(handle.get_thrust_policy(), thrust::make_constant_iterator(invalid_value), thrust::make_constant_iterator(invalid_value) + edge_ids_to_lookup.size(), @@ -271,18 +262,17 @@ struct search_container_t::search_container_imp for (size_t idx = 0; idx < h_unique_types.size(); idx++) { auto typ = h_unique_types[idx]; - auto start_ptr = tmp_edge_ids_to_lookup.begin(); - size_t span_size = 0; + auto tmp_edge_ids_begin = tmp_edge_ids_to_lookup.begin(); + size_t span_size = 0; if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { - auto xx = typ_to_local_idx_map[typ]; - - start_ptr = tmp_edge_ids_to_lookup.begin() + h_type_offsets[xx]; - span_size = h_type_offsets[xx + 1] - h_type_offsets[xx]; + auto local_idx = typ_to_local_idx_map[typ]; + tmp_edge_ids_begin = tmp_edge_ids_to_lookup.begin() + h_type_offsets[local_idx]; + span_size = h_type_offsets[local_idx + 1] - h_type_offsets[local_idx]; } auto optional_value_buffer = src_dst_from_edge_id_and_type( - handle, raft::device_span{start_ptr, span_size}, typ, multi_gpu); + handle, raft::device_span{tmp_edge_ids_begin, span_size}, typ, multi_gpu); if (optional_value_buffer.has_value()) { if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { @@ -302,6 +292,13 @@ struct search_container_t::search_container_imp return std::make_optional(std::move(output_value_buffer)); } + + private: + using container_t = + std::unordered_map>; + using store_t = typename container_t::mapped_type; + container_t edge_type_to_kv_store; }; template @@ -365,105 +362,6 @@ search_container_t::src_dst_from_edge_id_and_ty } namespace detail { -template -std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup) -{ - using value_t = typename EdgeTypeAndIdToSrcDstLookupContainerType::value_type; - - static_assert(std::is_same_v>); - - static_assert(std::is_integral_v); - static_assert(std::is_integral_v); - static_assert(is_arithmetic_or_thrust_tuple_of_arithmetic::value); - - static_assert( - std::is_same_v, - "edge_id_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_id_type"); - static_assert( - std::is_same_v, - "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); - - rmm::device_uvector output_srcs(edge_ids_to_lookup.size(), handle.get_stream()); - rmm::device_uvector output_dsts(edge_ids_to_lookup.size(), handle.get_stream()); - - auto constexpr invalid_vertex_id = cugraph::invalid_vertex_id::value; - thrust::fill( - handle.get_thrust_policy(), output_srcs.begin(), output_srcs.end(), invalid_vertex_id); - thrust::fill( - handle.get_thrust_policy(), output_dsts.begin(), output_dsts.end(), invalid_vertex_id); - - auto optional_value_buffer = search_container.src_dst_from_edge_id_and_type( - handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); - - if (optional_value_buffer.has_value()) { - thrust::copy( - handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), - cugraph::get_dataframe_buffer_end((*optional_value_buffer)), - thrust::make_zip_iterator(thrust::make_tuple(output_srcs.begin(), output_dsts.begin()))); - } - return std::make_tuple(std::move(output_srcs), std::move(output_dsts)); -} - -template -std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup) -{ - using value_t = typename EdgeTypeAndIdToSrcDstLookupContainerType::value_type; - - static_assert(std::is_same_v>); - - static_assert(std::is_integral_v); - static_assert(std::is_integral_v); - static_assert(is_arithmetic_or_thrust_tuple_of_arithmetic::value); - - assert(edge_ids_to_lookup.size() == edge_types_to_lookup.size()); - - static_assert( - std::is_same_v, - "edge_id_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_id_type"); - static_assert( - std::is_same_v, - "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); - - rmm::device_uvector output_srcs(edge_ids_to_lookup.size(), handle.get_stream()); - rmm::device_uvector output_dsts(edge_ids_to_lookup.size(), handle.get_stream()); - - auto constexpr invalid_vertex_id = cugraph::invalid_vertex_id::value; - thrust::fill( - handle.get_thrust_policy(), output_srcs.begin(), output_srcs.end(), invalid_vertex_id); - thrust::fill( - handle.get_thrust_policy(), output_dsts.begin(), output_dsts.end(), invalid_vertex_id); - - auto optional_value_buffer = search_container.src_dst_from_edge_id_and_type( - handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); - - if (optional_value_buffer.has_value()) { - thrust::copy( - handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), - cugraph::get_dataframe_buffer_end((*optional_value_buffer)), - thrust::make_zip_iterator(thrust::make_tuple(output_srcs.begin(), output_dsts.begin()))); - } - return std::make_tuple(std::move(output_srcs), std::move(output_dsts)); -} template ); static_assert(std::is_integral_v); - static_assert(is_arithmetic_or_thrust_tuple_of_arithmetic::value); - static_assert(std::is_same_v>); static_assert( @@ -1050,6 +945,85 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku return search_container; } + +template +std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup) +{ + using value_t = typename EdgeTypeAndIdToSrcDstLookupContainerType::value_type; + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + static_assert(std::is_same_v>); + + static_assert( + std::is_same_v, + "edge_id_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_id_type"); + static_assert( + std::is_same_v, + "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); + + rmm::device_uvector output_srcs(edge_ids_to_lookup.size(), handle.get_stream()); + rmm::device_uvector output_dsts(edge_ids_to_lookup.size(), handle.get_stream()); + + auto optional_value_buffer = search_container.src_dst_from_edge_id_and_type( + handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); + + thrust::copy( + handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), + cugraph::get_dataframe_buffer_end((*optional_value_buffer)), + thrust::make_zip_iterator(thrust::make_tuple(output_srcs.begin(), output_dsts.begin()))); + + return std::make_tuple(std::move(output_srcs), std::move(output_dsts)); +} + +template +std::tuple, rmm::device_uvector> +lookup_src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup) +{ + using value_t = typename EdgeTypeAndIdToSrcDstLookupContainerType::value_type; + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + static_assert(std::is_same_v>); + + assert(edge_ids_to_lookup.size() == edge_types_to_lookup.size()); + + static_assert( + std::is_same_v, + "edge_id_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_id_type"); + static_assert( + std::is_same_v, + "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); + + rmm::device_uvector output_srcs(edge_ids_to_lookup.size(), handle.get_stream()); + rmm::device_uvector output_dsts(edge_ids_to_lookup.size(), handle.get_stream()); + + auto optional_value_buffer = search_container.src_dst_from_edge_id_and_type( + handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); + + thrust::copy( + handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), + cugraph::get_dataframe_buffer_end((*optional_value_buffer)), + thrust::make_zip_iterator(thrust::make_tuple(output_srcs.begin(), output_dsts.begin()))); + return std::make_tuple(std::move(output_srcs), std::move(output_dsts)); +} } // namespace detail template From e407ac6b8447d9e5ef29f7c1356d8c9461083680 Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 18:51:45 +0200 Subject: [PATCH 10/26] Check if value_t is thrust tuple of integral --- cpp/include/cugraph/src_dst_lookup_container.hpp | 2 +- .../cugraph/utilities/thrust_tuple_utils.hpp | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index 5f05067b11b..bed00d849e7 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -61,7 +61,7 @@ class search_container_t { static_assert(std::is_integral_v); static_assert(std::is_integral_v); - static_assert(is_arithmetic_or_thrust_tuple_of_arithmetic::value); + static_assert(is_thrust_tuple_of_integral::value); ~search_container_t(); search_container_t(); diff --git a/cpp/include/cugraph/utilities/thrust_tuple_utils.hpp b/cpp/include/cugraph/utilities/thrust_tuple_utils.hpp index 304a5b94bd6..2c36ed33359 100644 --- a/cpp/include/cugraph/utilities/thrust_tuple_utils.hpp +++ b/cpp/include/cugraph/utilities/thrust_tuple_utils.hpp @@ -113,6 +113,19 @@ struct is_thrust_tuple_of_arithmetic> { static constexpr bool value = (... && is_valid); }; +template +struct is_thrust_tuple_of_integral : std::false_type {}; + +template +struct is_thrust_tuple_of_integral> { + private: + template + static constexpr bool is_valid = std::is_integral_v || std::is_same_v; + + public: + static constexpr bool value = (... && is_valid); +}; + template struct is_std_tuple : std::false_type {}; From 61f98d6501fbe276d43f3e4d45f0404a6ca7c32a Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 20:11:58 +0200 Subject: [PATCH 11/26] Address PR comments --- cpp/include/cugraph/algorithms.hpp | 81 ------- cpp/include/cugraph/sampling_functions.hpp | 81 +++++++ .../cugraph/src_dst_lookup_container.hpp | 18 +- cpp/src/lookup/lookup_src_dst_impl.cuh | 224 ++++++++---------- cpp/src/lookup/lookup_src_dst_mg.cu | 36 +-- cpp/src/lookup/lookup_src_dst_sg.cu | 36 +-- cpp/tests/lookup/lookup_src_dst_test.cpp | 3 +- cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 3 +- 8 files changed, 233 insertions(+), 249 deletions(-) diff --git a/cpp/include/cugraph/algorithms.hpp b/cpp/include/cugraph/algorithms.hpp index 2fbefd3b6d4..cc42399f091 100644 --- a/cpp/include/cugraph/algorithms.hpp +++ b/cpp/include/cugraph/algorithms.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include @@ -2413,86 +2412,6 @@ std::tuple, weight_t> approximate_weighted_matchin raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_weight_view); - -/* - * @brief Build map to lookup source and destination using edge id and type - * - * @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 edge_type_t Type of edge types. 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_id_view View object holding edge ids of the edges of the graph pointed @p graph_view - * @param edge_type_view View object holding edge types of the edges of the graph pointed @p - * graph_view - * @return An object of type cugraph::search_container_t that encapsulates edge id and type to - * source and destination lookup map. - */ -template -search_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( - raft::handle_t const& handle, - graph_view_t const& graph_view, - edge_property_view_t edge_id_view, - edge_property_view_t edge_type_view); - -/* - * @brief Lookup edge sources and destinations using edge ids and an edge type - * - * @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 edge_type_t Type of edge types. 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 search_container Object of type cugraph::search_container_t that encapsulates edge id and - * type to source and destination lookup map. - * @param edge_ids_to_lookup Device span of edge ids to lookup - * @param edge_type_to_lookup Type of the edges corresponding to edge ids in @p edge_ids_to_lookup - * @return A tuple of device vector containing edge sources and destinations for edge ids - * in @p edge_ids_to_lookup and edge type @. If an edge id in @p edge_ids_to_lookup or - * edge type @edge_type_to_lookup is not found, the corresponding entry in the device vectors of - * the returned tuple will contain cugraph::invalid_vertex_id. - */ -template -std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& - search_container, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup); - -/* - * @brief Lookup edge sources and destinations using edge ids and edge types - * - * @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 edge_type_t Type of edge types. 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 search_container Object of type cugraph::search_container_t that encapsulates edge id and - * type to source and destination lookup map. - * @param edge_ids_to_lookup Device span of edge ids to lookup - * @param edge_types_to_lookup Device span of edge types corresponding to the edge ids - * in @p edge_ids_to_lookup - * @return A tuple of device vector containing edge sources and destinations for the edge ids - * in @p edge_ids_to_lookup and the edge types in @p edge_types_to_lookup. If an edge id in - * @p edge_ids_to_lookup or edge type in @p edge_types_to_lookup is not found, the - * corresponding entry in the device vectors of the returned tuple will contain - * cugraph::invalid_vertex_id. - */ -template -std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( - raft::handle_t const& handle, - search_container_t> const& - search_container, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup); } // namespace cugraph /** diff --git a/cpp/include/cugraph/sampling_functions.hpp b/cpp/include/cugraph/sampling_functions.hpp index a4d7a162a90..002baf34597 100644 --- a/cpp/include/cugraph/sampling_functions.hpp +++ b/cpp/include/cugraph/sampling_functions.hpp @@ -15,6 +15,8 @@ */ #pragma once +#include + #include #include @@ -317,5 +319,84 @@ sort_sampled_edgelist(raft::handle_t const& handle, size_t num_hops, bool src_is_major = true, bool do_expensive_check = false); +/* + * @brief Build map to lookup source and destination using edge id and type + * + * @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 edge_type_t Type of edge types. 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_id_view View object holding edge ids of the edges of the graph pointed @p graph_view + * @param edge_type_view View object holding edge types of the edges of the graph pointed @p + * graph_view + * @return An object of type cugraph::lookup_container_t that encapsulates edge id and type to + * source and destination lookup map. + */ +template +lookup_container_t> +build_edge_id_and_type_to_src_dst_lookup_map( + raft::handle_t const& handle, + graph_view_t const& graph_view, + edge_property_view_t edge_id_view, + edge_property_view_t edge_type_view); + +/* + * @brief Lookup edge sources and destinations using edge ids and a single edge type + * + * @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 edge_type_t Type of edge types. 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 search_container Object of type cugraph::lookup_container_t that encapsulates edge id and + * type to source and destination lookup map. + * @param edge_ids_to_lookup Device span of edge ids to lookup + * @param edge_type_to_lookup Type of the edges corresponding to edge ids in @p edge_ids_to_lookup + * @return A tuple of device vector containing edge sources and destinations for edge ids + * in @p edge_ids_to_lookup and edge type @. If an edge id in @p edge_ids_to_lookup or + * edge type @edge_type_to_lookup is not found, the corresponding entry in the device vectors of + * the returned tuple will contain cugraph::invalid_vertex_id. + */ +template +std::tuple, rmm::device_uvector> +lookup_endpoints_for_edge_ids_of_single_type( + raft::handle_t const& handle, + lookup_container_t> const& + search_container, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup); + +/* + * @brief Lookup edge sources and destinations using edge ids and edge types + * + * @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 edge_type_t Type of edge types. 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 search_container Object of type cugraph::lookup_container_t that encapsulates edge id and + * type to source and destination lookup map. + * @param edge_ids_to_lookup Device span of edge ids to lookup + * @param edge_types_to_lookup Device span of edge types corresponding to the edge ids + * in @p edge_ids_to_lookup + * @return A tuple of device vector containing edge sources and destinations for the edge ids + * in @p edge_ids_to_lookup and the edge types in @p edge_types_to_lookup. If an edge id in + * @p edge_ids_to_lookup or edge type in @p edge_types_to_lookup is not found, the + * corresponding entry in the device vectors of the returned tuple will contain + * cugraph::invalid_vertex_id. + */ +template +std::tuple, rmm::device_uvector> +lookup_endpoints_for_edge_ids_and_types( + raft::handle_t const& handle, + lookup_container_t> const& + search_container, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup); } // namespace cugraph diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index bed00d849e7..e1533f9b5df 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -49,10 +49,10 @@ constexpr TupleType invalid_of_thrust_tuple_of_integral() } template -class search_container_t { +class lookup_container_t { template - struct search_container_impl; - std::unique_ptr> pimpl; + struct lookup_container_impl; + std::unique_ptr> pimpl; public: using edge_id_type = edge_id_t; @@ -63,12 +63,12 @@ class search_container_t { static_assert(std::is_integral_v); static_assert(is_thrust_tuple_of_integral::value); - ~search_container_t(); - search_container_t(); - search_container_t(raft::handle_t const& handle, + ~lookup_container_t(); + lookup_container_t(); + lookup_container_t(raft::handle_t const& handle, std::vector types, std::vector type_counts); - search_container_t(const search_container_t&); + lookup_container_t(const lookup_container_t&); void insert(raft::handle_t const& handle, edge_type_t typ, @@ -76,13 +76,13 @@ class search_container_t { decltype(cugraph::allocate_dataframe_buffer( 0, rmm::cuda_stream_view{}))&& values_to_insert); - std::optional(0, rmm::cuda_stream_view{}))> + decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) src_dst_from_edge_id_and_type(raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup, bool multi_gpu) const; - std::optional(0, rmm::cuda_stream_view{}))> + decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) src_dst_from_edge_id_and_type(raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup, diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index 82a91d87336..dfab97db033 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -31,7 +31,7 @@ namespace cugraph { template template -struct search_container_t::search_container_impl { +struct lookup_container_t::lookup_container_impl { static_assert(std::is_integral_v); static_assert(std::is_integral_v); @@ -39,9 +39,9 @@ struct search_container_t::search_container_imp static_assert(std::is_same_v); static_assert(std::is_same_v); - ~search_container_impl() {} - search_container_impl() {} - search_container_impl(raft::handle_t const& handle, + ~lookup_container_impl() {} + lookup_container_impl() {} + lookup_container_impl(raft::handle_t const& handle, std::vector typs, std::vector typ_freqs) { @@ -81,7 +81,7 @@ struct search_container_t::search_container_imp } } - std::optional(0, rmm::cuda_stream_view{}))> + decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) src_dst_from_edge_id_and_type(raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup, @@ -107,7 +107,9 @@ struct search_container_t::search_container_imp thrust::make_constant_iterator(invalid_value) + edge_ids_to_lookup.size(), cugraph::get_dataframe_buffer_begin(value_buffer)); - return std::make_optional(std::move(value_buffer)); + // FIXME: we are assuming value_t is tuple of size 2 + return std::make_tuple(std::move(std::get<0>(value_buffer)), + std::move(std::get<1>(value_buffer))); } if (multi_gpu) { @@ -137,10 +139,12 @@ struct search_container_t::search_container_imp handle.get_stream()); } - return std::make_optional(std::move(value_buffer)); + // FIXME: we are assuming value_t is tuple of size 2 + return std::make_tuple(std::move(std::get<0>(value_buffer)), + std::move(std::get<1>(value_buffer))); } - std::optional(0, rmm::cuda_stream_view{}))> + decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) src_dst_from_edge_id_and_type(raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup, @@ -216,7 +220,7 @@ struct search_container_t::search_container_imp std::unordered_map typ_to_local_idx_map{}; - RAFT_CUDA_TRY(cudaDeviceSynchronize()); + handle.sync_stream(); for (size_t idx = 0; idx < h_unique_types.size(); idx++) { typ_to_local_idx_map[h_unique_types[idx]] = idx; @@ -271,17 +275,15 @@ struct search_container_t::search_container_imp span_size = h_type_offsets[local_idx + 1] - h_type_offsets[local_idx]; } - auto optional_value_buffer = src_dst_from_edge_id_and_type( + auto value_buffer_typ = src_dst_from_edge_id_and_type( handle, raft::device_span{tmp_edge_ids_begin, span_size}, typ, multi_gpu); - if (optional_value_buffer.has_value()) { - if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { - thrust::copy(handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), - cugraph::get_dataframe_buffer_end((*optional_value_buffer)), - cugraph::get_dataframe_buffer_begin(output_value_buffer) + - h_type_offsets[typ_to_local_idx_map[typ]]); - } + if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { + thrust::copy(handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin(value_buffer_typ), + cugraph::get_dataframe_buffer_end(value_buffer_typ), + cugraph::get_dataframe_buffer_begin(output_value_buffer) + + h_type_offsets[typ_to_local_idx_map[typ]]); } } @@ -290,7 +292,9 @@ struct search_container_t::search_container_imp original_idxs.end(), cugraph::get_dataframe_buffer_begin(output_value_buffer)); - return std::make_optional(std::move(output_value_buffer)); + // FIXME: we are assuming value_t is tuple of size 2 + return std::make_tuple(std::move(std::get<0>(output_value_buffer)), + std::move(std::get<1>(output_value_buffer))); } private: @@ -302,32 +306,32 @@ struct search_container_t::search_container_imp }; template -search_container_t::~search_container_t() +lookup_container_t::~lookup_container_t() { pimpl.reset(); } template -search_container_t::search_container_t() - : pimpl{std::make_unique>()} +lookup_container_t::lookup_container_t() + : pimpl{std::make_unique>()} { } template -search_container_t::search_container_t( +lookup_container_t::lookup_container_t( raft::handle_t const& handle, std::vector typs, std::vector typ_freqs) - : pimpl{std::make_unique>( + : pimpl{std::make_unique>( handle, typs, typ_freqs)} { } template -search_container_t::search_container_t(const search_container_t&) +lookup_container_t::lookup_container_t(const lookup_container_t&) { } template -void search_container_t::insert( +void lookup_container_t::insert( raft::handle_t const& handle, edge_type_t type, raft::device_span edge_ids_to_insert, @@ -338,8 +342,8 @@ void search_container_t::insert( } template -std::optional(0, rmm::cuda_stream_view{}))> -search_container_t::src_dst_from_edge_id_and_type( +decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) +lookup_container_t::src_dst_from_edge_id_and_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup, @@ -350,8 +354,8 @@ search_container_t::src_dst_from_edge_id_and_ty } template -std::optional(0, rmm::cuda_stream_view{}))> -search_container_t::src_dst_from_edge_id_and_type( +decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) +lookup_container_t::src_dst_from_edge_id_and_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup, @@ -416,11 +420,11 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku number_of_edges_partition); } - [[maybe_unused]] auto edgelist_ids = std::make_optional>( - number_of_active_edges_partition, handle.get_stream()); + [[maybe_unused]] auto edgelist_ids = + rmm::device_uvector(number_of_active_edges_partition, handle.get_stream()); - auto edgelist_types = std::make_optional>( - number_of_active_edges_partition, handle.get_stream()); + auto edgelist_types = + rmm::device_uvector(number_of_active_edges_partition, handle.get_stream()); auto edge_partition_mask_view = graph_view.has_edge_mask() @@ -436,26 +440,26 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku edge_id_view.value_firsts()[local_ep_idx], edge_id_view.value_firsts()[local_ep_idx] + number_of_edges_partition, (*edge_partition_mask_view).value_first(), - (*edgelist_ids).begin()); + edgelist_ids.begin()); } detail::copy_if_mask_set( handle, edge_type_view.value_firsts()[local_ep_idx], edge_type_view.value_firsts()[local_ep_idx] + number_of_edges_partition, (*edge_partition_mask_view).value_first(), - (*edgelist_types).begin()); + edgelist_types.begin()); } else { if constexpr (multi_gpu) { thrust::copy(handle.get_thrust_policy(), edge_id_view.value_firsts()[local_ep_idx], edge_id_view.value_firsts()[local_ep_idx] + number_of_edges_partition, - (*edgelist_ids).begin()); + edgelist_ids.begin()); } thrust::copy(handle.get_thrust_policy(), edge_type_view.value_firsts()[local_ep_idx], edge_type_view.value_firsts()[local_ep_idx] + number_of_edges_partition, - (*edgelist_types).begin()); + edgelist_types.begin()); } std::vector h_unique_gpu_ids{}; @@ -476,25 +480,24 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku // destination gpu id from edge id. NB: edgelist_ids will holds gpu ids after the following // thrust::transform thrust::transform(handle.get_thrust_policy(), - (*edgelist_ids).begin(), - (*edgelist_ids).end(), - (*edgelist_ids).begin(), + edgelist_ids.begin(), + edgelist_ids.end(), + edgelist_ids.begin(), [key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ comm_size, major_comm_size, minor_comm_size}] __device__(auto eid) { return key_func(eid); }); - thrust::sort(handle.get_thrust_policy(), - thrust::make_zip_iterator( - thrust::make_tuple((*edgelist_ids).begin(), (*edgelist_types).begin())), - thrust::make_zip_iterator( - thrust::make_tuple((*edgelist_ids).end(), (*edgelist_types).end()))); + thrust::sort( + handle.get_thrust_policy(), + thrust::make_zip_iterator(thrust::make_tuple(edgelist_ids.begin(), edgelist_types.begin())), + thrust::make_zip_iterator(thrust::make_tuple(edgelist_ids.end(), edgelist_types.end()))); auto nr_unique_gpu_ids = thrust::count_if(handle.get_thrust_policy(), thrust::make_counting_iterator(size_t{0}), - thrust::make_counting_iterator((*edgelist_ids).size()), - detail::is_first_in_run_t{(*edgelist_ids).data()}); + thrust::make_counting_iterator(edgelist_ids.size()), + detail::is_first_in_run_t{edgelist_ids.data()}); rmm::device_uvector unique_gpu_ids(nr_unique_gpu_ids, handle.get_stream()); rmm::device_uvector gpu_offsets(nr_unique_gpu_ids + 1, handle.get_stream()); @@ -502,8 +505,8 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku thrust::fill(handle.get_thrust_policy(), gpu_offsets.begin(), gpu_offsets.end(), edge_t{0}); thrust::reduce_by_key(handle.get_thrust_policy(), - (*edgelist_ids).begin(), - (*edgelist_ids).end(), + edgelist_ids.begin(), + edgelist_ids.end(), thrust::make_constant_iterator(size_t{1}), unique_gpu_ids.begin(), gpu_offsets.begin()); @@ -522,14 +525,14 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku h_gpu_offsets.data(), gpu_offsets.data(), gpu_offsets.size(), handle.get_stream()); } else { - thrust::sort(handle.get_thrust_policy(), (*edgelist_types).begin(), (*edgelist_types).end()); + thrust::sort(handle.get_thrust_policy(), edgelist_types.begin(), edgelist_types.end()); h_unique_gpu_ids.resize(size_t{1}); h_unique_gpu_ids[0] = 0; h_gpu_offsets.resize(h_unique_gpu_ids.size() + 1); h_gpu_offsets[0] = 0; - h_gpu_offsets[1] = (*edgelist_types).size(); + h_gpu_offsets[1] = edgelist_types.size(); } // @@ -547,20 +550,19 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku for (size_t idx = 0; idx < h_unique_gpu_ids.size(); ++idx) { auto gpu_id = h_unique_gpu_ids[idx]; - auto nr_uniqe_types_segment = - thrust::count_if(handle.get_thrust_policy(), - thrust::make_counting_iterator(size_t{0}), - thrust::make_counting_iterator( - static_cast(h_gpu_offsets[idx + 1] - h_gpu_offsets[idx])), - detail::is_first_in_run_t{(*edgelist_types).data() + - h_gpu_offsets[idx]}); + auto nr_uniqe_types_segment = thrust::count_if( + handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator( + static_cast(h_gpu_offsets[idx + 1] - h_gpu_offsets[idx])), + detail::is_first_in_run_t{edgelist_types.data() + h_gpu_offsets[idx]}); unique_types_segment.resize(nr_uniqe_types_segment, handle.get_stream()); type_freqs_segment.resize(nr_uniqe_types_segment, handle.get_stream()); thrust::reduce_by_key(handle.get_thrust_policy(), - (*edgelist_types).begin() + h_gpu_offsets[idx], - (*edgelist_types).begin() + h_gpu_offsets[idx + 1], + edgelist_types.begin() + h_gpu_offsets[idx], + edgelist_types.begin() + h_gpu_offsets[idx + 1], thrust::make_constant_iterator(size_t{1}), unique_types_segment.begin(), type_freqs_segment.begin()); @@ -805,10 +807,9 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku rmm::device_uvector edgelist_majors(number_of_local_edges, handle.get_stream()); rmm::device_uvector edgelist_minors(edgelist_majors.size(), handle.get_stream()); - auto edgelist_ids = - std::make_optional>(edgelist_majors.size(), handle.get_stream()); - auto edgelist_types = std::make_optional>( - edgelist_majors.size(), handle.get_stream()); + auto edgelist_ids = rmm::device_uvector(edgelist_majors.size(), handle.get_stream()); + auto edgelist_types = + rmm::device_uvector(edgelist_majors.size(), handle.get_stream()); detail::decompress_edge_partition_to_edgelist( handle, @@ -828,8 +829,8 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku raft::device_span(edgelist_majors.data(), number_of_local_edges), raft::device_span(edgelist_minors.data(), number_of_local_edges), std::nullopt, - std::make_optional>((*edgelist_ids).data(), number_of_local_edges), - std::make_optional>((*edgelist_types).data(), + std::make_optional>(edgelist_ids.data(), number_of_local_edges), + std::make_optional>(edgelist_types.data(), number_of_local_edges), graph_view.local_edge_partition_segment_offsets(local_ep_idx)); @@ -846,18 +847,17 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku // Shuffle to the proper GPUs std::forward_as_tuple( - std::tie(edgelist_majors, edgelist_minors, (*edgelist_ids), (*edgelist_types)), - std::ignore) = + std::tie(edgelist_majors, edgelist_minors, edgelist_ids, edgelist_types), std::ignore) = cugraph::groupby_gpu_id_and_shuffle_values( handle.get_comms(), thrust::make_zip_iterator(thrust::make_tuple(edgelist_majors.begin(), edgelist_minors.begin(), - (*edgelist_ids).begin(), - (*edgelist_types).begin())), + edgelist_ids.begin(), + edgelist_types.begin())), thrust::make_zip_iterator(thrust::make_tuple(edgelist_majors.end(), edgelist_minors.end(), - (*edgelist_ids).end(), - (*edgelist_types).end())), + edgelist_ids.end(), + edgelist_types.end())), [key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ comm_size, @@ -871,18 +871,16 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku // auto itr_to_triple = thrust::make_zip_iterator( - edgelist_majors.begin(), edgelist_minors.begin(), (*edgelist_ids).begin()); + edgelist_majors.begin(), edgelist_minors.begin(), edgelist_ids.begin()); - thrust::sort_by_key(handle.get_thrust_policy(), - (*edgelist_types).begin(), - (*edgelist_types).end(), - itr_to_triple); + thrust::sort_by_key( + handle.get_thrust_policy(), edgelist_types.begin(), edgelist_types.end(), itr_to_triple); auto nr_uniqe_edge_types_partition = thrust::count_if(handle.get_thrust_policy(), thrust::make_counting_iterator(size_t{0}), - thrust::make_counting_iterator((*edgelist_types).size()), - detail::is_first_in_run_t{(*edgelist_types).data()}); + thrust::make_counting_iterator(edgelist_types.size()), + detail::is_first_in_run_t{edgelist_types.data()}); rmm::device_uvector unique_types(nr_uniqe_edge_types_partition, handle.get_stream()); @@ -892,8 +890,8 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku thrust::fill(handle.get_thrust_policy(), type_offsets.begin(), type_offsets.end(), edge_t{0}); thrust::reduce_by_key(handle.get_thrust_policy(), - (*edgelist_types).begin(), - (*edgelist_types).end(), + edgelist_types.begin(), + edgelist_types.end(), thrust::make_constant_iterator(size_t{1}), unique_types.begin(), type_offsets.begin()); @@ -934,12 +932,11 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku values_to_insert))>::value_type, value_t>); - search_container.insert( - handle, - typ, - raft::device_span((*edgelist_ids).begin() + h_type_offsets[idx], - nr_elements_to_insert), - std::move(values_to_insert)); + search_container.insert(handle, + typ, + raft::device_span(edgelist_ids.begin() + h_type_offsets[idx], + nr_elements_to_insert), + std::move(values_to_insert)); } } @@ -952,7 +949,7 @@ template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_of_single_type( raft::handle_t const& handle, EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, raft::device_span edge_ids_to_lookup, @@ -970,19 +967,11 @@ lookup_src_dst_from_edge_id_and_type( std::is_same_v, "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); - rmm::device_uvector output_srcs(edge_ids_to_lookup.size(), handle.get_stream()); - rmm::device_uvector output_dsts(edge_ids_to_lookup.size(), handle.get_stream()); - - auto optional_value_buffer = search_container.src_dst_from_edge_id_and_type( + auto value_buffer = search_container.src_dst_from_edge_id_and_type( handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); - thrust::copy( - handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), - cugraph::get_dataframe_buffer_end((*optional_value_buffer)), - thrust::make_zip_iterator(thrust::make_tuple(output_srcs.begin(), output_dsts.begin()))); - - return std::make_tuple(std::move(output_srcs), std::move(output_dsts)); + return std::make_tuple(std::move(std::get<0>(value_buffer)), + std::move(std::get<1>(value_buffer))); } template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_and_types( raft::handle_t const& handle, EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, raft::device_span edge_ids_to_lookup, @@ -1011,53 +1000,46 @@ lookup_src_dst_from_edge_id_and_type( std::is_same_v, "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); - rmm::device_uvector output_srcs(edge_ids_to_lookup.size(), handle.get_stream()); - rmm::device_uvector output_dsts(edge_ids_to_lookup.size(), handle.get_stream()); - - auto optional_value_buffer = search_container.src_dst_from_edge_id_and_type( + auto value_buffer = search_container.src_dst_from_edge_id_and_type( handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); - thrust::copy( - handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin((*optional_value_buffer)), - cugraph::get_dataframe_buffer_end((*optional_value_buffer)), - thrust::make_zip_iterator(thrust::make_tuple(output_srcs.begin(), output_dsts.begin()))); - return std::make_tuple(std::move(output_srcs), std::move(output_dsts)); + return std::make_tuple(std::move(std::get<0>(value_buffer)), + std::move(std::get<1>(value_buffer))); } } // namespace detail template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_of_single_type( raft::handle_t const& handle, - search_container_t> const& + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup) { - using m_t = search_container_t>; + using m_t = lookup_container_t>; return detail:: - lookup_src_dst_from_edge_id_and_type( + lookup_endpoints_for_edge_ids_of_single_type( handle, search_container, edge_ids_to_lookup, edge_type_to_lookup); } template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_and_types( raft::handle_t const& handle, - search_container_t> const& + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup) { - using m_t = search_container_t>; + using m_t = lookup_container_t>; return detail:: - lookup_src_dst_from_edge_id_and_type( + lookup_endpoints_for_edge_ids_and_types( handle, search_container, edge_ids_to_lookup, edge_types_to_lookup); } template -search_container_t> +lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, @@ -1065,7 +1047,7 @@ build_edge_id_and_type_to_src_dst_lookup_map( edge_property_view_t edge_type_view) { using graph_view_t = graph_view_t; - using return_t = search_container_t>; + using return_t = lookup_container_t>; return detail::build_edge_id_and_type_to_src_dst_lookup_map>; -template class search_container_t>; -template class search_container_t>; +template class lookup_container_t>; +template class lookup_container_t>; +template class lookup_container_t>; -template search_container_t> +template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, @@ -30,20 +30,20 @@ build_edge_id_and_type_to_src_dst_lookup_map( edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_of_single_type( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_and_types( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -template search_container_t> +template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, @@ -51,20 +51,20 @@ build_edge_id_and_type_to_src_dst_lookup_map( edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_of_single_type( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_and_types( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -template search_container_t> +template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, @@ -72,16 +72,16 @@ build_edge_id_and_type_to_src_dst_lookup_map( edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_of_single_type( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_and_types( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); diff --git a/cpp/src/lookup/lookup_src_dst_sg.cu b/cpp/src/lookup/lookup_src_dst_sg.cu index 1ded6b740f1..1c4d4e37d64 100644 --- a/cpp/src/lookup/lookup_src_dst_sg.cu +++ b/cpp/src/lookup/lookup_src_dst_sg.cu @@ -18,11 +18,11 @@ namespace cugraph { -template class search_container_t>; -template class search_container_t>; -template class search_container_t>; +template class lookup_container_t>; +template class lookup_container_t>; +template class lookup_container_t>; -template search_container_t> +template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, @@ -30,20 +30,20 @@ build_edge_id_and_type_to_src_dst_lookup_map( edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_of_single_type( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, int32_t const edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_and_types( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -template search_container_t> +template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, @@ -51,20 +51,20 @@ build_edge_id_and_type_to_src_dst_lookup_map( edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_of_single_type( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_and_types( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -template search_container_t> +template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, @@ -72,15 +72,15 @@ build_edge_id_and_type_to_src_dst_lookup_map( edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_of_single_type( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_src_dst_from_edge_id_and_type( +lookup_endpoints_for_edge_ids_and_types( raft::handle_t const& handle, - search_container_t> const& search_container, + lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp index 4316dd2f1ce..35312878e83 100644 --- a/cpp/tests/lookup/lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -224,7 +225,7 @@ class Tests_SGLookupEdgeSrcDst d_mg_edge_types = cugraph::test::to_device(handle, h_mg_edge_types); auto [srcs, dsts] = - cugraph::lookup_src_dst_from_edge_id_and_type( + cugraph::lookup_endpoints_for_edge_ids_and_types( handle, search_container, raft::device_span((*d_mg_edge_ids).begin(), (*d_mg_edge_ids).size()), diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp index 10a24d075d8..0bbf32525ff 100644 --- a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -248,7 +249,7 @@ class Tests_MGLookupEdgeSrcDst d_mg_edge_types = cugraph::test::to_device(*handle_, h_mg_edge_types); auto [srcs, dsts] = - cugraph::lookup_src_dst_from_edge_id_and_type( + cugraph::lookup_endpoints_for_edge_ids_and_types( *handle_, search_container, raft::device_span((*d_mg_edge_ids).begin(), (*d_mg_edge_ids).size()), From 0e80b4b9897a7dd4e1dc5822e170fb79e70b0d90 Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 20:20:34 +0200 Subject: [PATCH 12/26] Address PR comments --- cpp/include/cugraph/sampling_functions.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cpp/include/cugraph/sampling_functions.hpp b/cpp/include/cugraph/sampling_functions.hpp index 002baf34597..c7ff74f93f0 100644 --- a/cpp/include/cugraph/sampling_functions.hpp +++ b/cpp/include/cugraph/sampling_functions.hpp @@ -344,7 +344,8 @@ build_edge_id_and_type_to_src_dst_lookup_map( edge_property_view_t edge_type_view); /* - * @brief Lookup edge sources and destinations using edge ids and a single edge type + * @brief Lookup edge sources and destinations using edge ids and a single edge type. + * Use this function to lookup endpoints of edges belonging to the same edge type. * * @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. @@ -371,7 +372,8 @@ lookup_endpoints_for_edge_ids_of_single_type( edge_type_t edge_type_to_lookup); /* - * @brief Lookup edge sources and destinations using edge ids and edge types + * @brief Lookup edge sources and destinations using edge ids and edge types. + * Use this function to lookup endpoints of edges belonging to different edge types. * * @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. From af1cb814d41abb1986567557e0255cee17731800 Mon Sep 17 00:00:00 2001 From: Naim Date: Wed, 29 May 2024 21:23:20 +0200 Subject: [PATCH 13/26] Address additional PR comments --- .../cugraph/src_dst_lookup_container.hpp | 22 ++++----- .../cugraph/utilities/dataframe_buffer.hpp | 8 +++ cpp/src/lookup/lookup_src_dst_impl.cuh | 49 ++++++++++--------- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index e1533f9b5df..0d8bb6c834d 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -76,17 +76,17 @@ class lookup_container_t { decltype(cugraph::allocate_dataframe_buffer( 0, rmm::cuda_stream_view{}))&& values_to_insert); - decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) - src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup, - bool multi_gpu) const; - - decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) - src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup, - bool multi_gpu) const; + dataframe_buffer_type_t src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const; + + dataframe_buffer_type_t src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const; }; } // namespace cugraph diff --git a/cpp/include/cugraph/utilities/dataframe_buffer.hpp b/cpp/include/cugraph/utilities/dataframe_buffer.hpp index d52160abd19..450e816bd96 100644 --- a/cpp/include/cugraph/utilities/dataframe_buffer.hpp +++ b/cpp/include/cugraph/utilities/dataframe_buffer.hpp @@ -207,6 +207,14 @@ auto get_dataframe_buffer_end(BufferType& buffer) std::make_index_sequence::value>(), buffer); } +template +struct dataframe_buffer_type { + using type = decltype(allocate_dataframe_buffer(size_t{0}, rmm::cuda_stream_view{})); +}; + +template +using dataframe_buffer_type_t = typename dataframe_buffer_type::type; + template , rmm::device_uvector>::value>* = nullptr> diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index dfab97db033..bd5eef25e6e 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -42,18 +42,18 @@ struct lookup_container_t::lookup_container_imp ~lookup_container_impl() {} lookup_container_impl() {} lookup_container_impl(raft::handle_t const& handle, - std::vector typs, - std::vector typ_freqs) + std::vector types, + std::vector type_counts) { auto invalid_key = cugraph::invalid_vertex_id::value; auto invalid_value = invalid_of_thrust_tuple_of_integral(); edge_type_to_kv_store = container_t{}; - edge_type_to_kv_store.reserve(typs.size()); + edge_type_to_kv_store.reserve(types.size()); - for (size_t idx = 0; idx < typs.size(); idx++) { - auto typ = typs[idx]; - size_t store_capacity = typ_freqs[idx]; + for (size_t idx = 0; idx < types.size(); idx++) { + auto typ = types[idx]; + size_t store_capacity = type_counts[idx]; edge_type_to_kv_store.insert( {typ, std::move(store_t(store_capacity, invalid_key, invalid_value, handle.get_stream()))}); @@ -81,11 +81,11 @@ struct lookup_container_t::lookup_container_imp } } - decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) - src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - edge_type_t edge_type_to_lookup, - bool multi_gpu) const + dataframe_buffer_type_t src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + edge_type_t edge_type_to_lookup, + bool multi_gpu) const { using store_t = typename container_t::mapped_type; const store_t* kv_store_object{nullptr}; @@ -102,10 +102,11 @@ struct lookup_container_t::lookup_container_imp value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); auto invalid_value = invalid_of_thrust_tuple_of_integral(); - thrust::copy(handle.get_thrust_policy(), - thrust::make_constant_iterator(invalid_value), - thrust::make_constant_iterator(invalid_value) + edge_ids_to_lookup.size(), - cugraph::get_dataframe_buffer_begin(value_buffer)); + + thrust::fill(handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin(value_buffer), + cugraph::get_dataframe_buffer_end(value_buffer), + invalid_value); // FIXME: we are assuming value_t is tuple of size 2 return std::make_tuple(std::move(std::get<0>(value_buffer)), @@ -144,11 +145,11 @@ struct lookup_container_t::lookup_container_imp std::move(std::get<1>(value_buffer))); } - decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) - src_dst_from_edge_id_and_type(raft::handle_t const& handle, - raft::device_span edge_ids_to_lookup, - raft::device_span edge_types_to_lookup, - bool multi_gpu) const + dataframe_buffer_type_t src_dst_from_edge_id_and_type( + raft::handle_t const& handle, + raft::device_span edge_ids_to_lookup, + raft::device_span edge_types_to_lookup, + bool multi_gpu) const { static_assert(std::is_integral_v); static_assert(std::is_integral_v); @@ -319,9 +320,9 @@ lookup_container_t::lookup_container_t() template lookup_container_t::lookup_container_t( - raft::handle_t const& handle, std::vector typs, std::vector typ_freqs) + raft::handle_t const& handle, std::vector types, std::vector type_counts) : pimpl{std::make_unique>( - handle, typs, typ_freqs)} + handle, types, type_counts)} { } @@ -342,7 +343,7 @@ void lookup_container_t::insert( } template -decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) +dataframe_buffer_type_t lookup_container_t::src_dst_from_edge_id_and_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, @@ -354,7 +355,7 @@ lookup_container_t::src_dst_from_edge_id_and_ty } template -decltype(cugraph::allocate_dataframe_buffer(0, rmm::cuda_stream_view{})) +dataframe_buffer_type_t lookup_container_t::src_dst_from_edge_id_and_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, From be642c9a4af063b8d0108c8caf4e9a4e8c95a837 Mon Sep 17 00:00:00 2001 From: Naim Date: Tue, 4 Jun 2024 17:19:01 +0200 Subject: [PATCH 14/26] Address aditional PR comments --- .../cugraph/src_dst_lookup_container.hpp | 3 +- cpp/src/detail/graph_partition_utils.cuh | 15 + cpp/src/lookup/lookup_src_dst_impl.cuh | 553 ++++++------------ cpp/src/lookup/lookup_src_dst_mg.cu | 8 +- cpp/src/lookup/lookup_src_dst_sg.cu | 7 +- .../community/mg_weighted_matching_test.cpp | 34 +- cpp/tests/lookup/lookup_src_dst_test.cpp | 81 ++- cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 81 ++- 8 files changed, 291 insertions(+), 491 deletions(-) diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index 0d8bb6c834d..9e0ca1a8c4e 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -73,8 +73,7 @@ class lookup_container_t { void insert(raft::handle_t const& handle, edge_type_t typ, raft::device_span edge_ids_to_insert, - decltype(cugraph::allocate_dataframe_buffer( - 0, rmm::cuda_stream_view{}))&& values_to_insert); + dataframe_buffer_type_t&& values_to_insert); dataframe_buffer_type_t src_dst_from_edge_id_and_type( raft::handle_t const& handle, diff --git a/cpp/src/detail/graph_partition_utils.cuh b/cpp/src/detail/graph_partition_utils.cuh index 957436459cd..8b10181e529 100644 --- a/cpp/src/detail/graph_partition_utils.cuh +++ b/cpp/src/detail/graph_partition_utils.cuh @@ -50,6 +50,21 @@ struct compute_gpu_id_from_ext_vertex_t { } }; +template +struct compute_gpu_id_from_ext_edge_t { + int comm_size{0}; + int major_comm_size{0}; + int minor_comm_size{0}; + + __host__ __device__ int operator()(edge_t e) const + { + cuco::detail::MurmurHash3_32 hash_func{}; + auto vertex_partition_id = static_cast(hash_func(e) % comm_size); + return partition_manager::compute_global_comm_rank_from_vertex_partition_id( + major_comm_size, minor_comm_size, vertex_partition_id); + } +}; + template struct compute_gpu_id_from_int_vertex_t { raft::device_span vertex_partition_range_lasts{}; diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index bd5eef25e6e..4b041273c76 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -14,12 +14,14 @@ * limitations under the License. */ #include "detail/graph_partition_utils.cuh" +#include "prims/extract_transform_e.cuh" #include "prims/kv_store.cuh" #include "utilities/collect_comm.cuh" #include #include #include +#include #include #include #include @@ -52,19 +54,22 @@ struct lookup_container_t::lookup_container_imp edge_type_to_kv_store.reserve(types.size()); for (size_t idx = 0; idx < types.size(); idx++) { - auto typ = types[idx]; + auto typ = types[idx]; + assert(typ != empty_type_); size_t store_capacity = type_counts[idx]; edge_type_to_kv_store.insert( - {typ, std::move(store_t(store_capacity, invalid_key, invalid_value, handle.get_stream()))}); + {typ, store_t(store_capacity, invalid_key, invalid_value, handle.get_stream())}); } + + edge_type_to_kv_store.insert( + {empty_type_, store_t(0, invalid_key, invalid_value, handle.get_stream())}); } void insert(raft::handle_t const& handle, edge_type_t type, raft::device_span edge_ids_to_insert, - decltype(cugraph::allocate_dataframe_buffer( - 0, rmm::cuda_stream_view{}))&& values_to_insert) + dataframe_buffer_type_t&& values_to_insert) { auto itr = edge_type_to_kv_store.find(type); @@ -98,6 +103,12 @@ struct lookup_container_t::lookup_container_imp kv_store_object = &(itr->second); } else { + // edge_type_t type_with_no_edges = std::numeric_limits::max() - 1; + kv_store_object = &(edge_type_to_kv_store.find(empty_type_)->second); + } + + /* + else { cugraph::resize_dataframe_buffer( value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); @@ -112,6 +123,7 @@ struct lookup_container_t::lookup_container_imp return std::make_tuple(std::move(std::get<0>(value_buffer)), std::move(std::get<1>(value_buffer))); } + */ if (multi_gpu) { auto& comm = handle.get_comms(); @@ -121,15 +133,13 @@ struct lookup_container_t::lookup_container_imp auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); auto const minor_comm_size = minor_comm.get_size(); - auto key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ - comm_size, major_comm_size, minor_comm_size}; - - value_buffer = cugraph::collect_values_for_keys(handle, - kv_store_object->view(), - edge_ids_to_lookup.begin(), - edge_ids_to_lookup.end(), - key_func); - + value_buffer = + cugraph::collect_values_for_keys(handle, + kv_store_object->view(), + edge_ids_to_lookup.begin(), + edge_ids_to_lookup.end(), + cugraph::detail::compute_gpu_id_from_ext_edge_t{ + comm_size, major_comm_size, minor_comm_size}); } else { cugraph::resize_dataframe_buffer( value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); @@ -219,21 +229,20 @@ struct lookup_container_t::lookup_container_imp raft::update_host( h_type_offsets.data(), type_offsets.data(), type_offsets.size(), handle.get_stream()); - std::unordered_map typ_to_local_idx_map{}; - handle.sync_stream(); + std::unordered_map typ_to_local_idx_map{}; for (size_t idx = 0; idx < h_unique_types.size(); idx++) { typ_to_local_idx_map[h_unique_types[idx]] = idx; } auto output_value_buffer = cugraph::allocate_dataframe_buffer(edge_ids_to_lookup.size(), handle.get_stream()); - auto invalid_value = invalid_of_thrust_tuple_of_integral(); - thrust::fill(handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin(output_value_buffer), - cugraph::get_dataframe_buffer_begin(output_value_buffer), - invalid_value); + // auto invalid_value = invalid_of_thrust_tuple_of_integral(); + // thrust::fill(handle.get_thrust_policy(), + // cugraph::get_dataframe_buffer_begin(output_value_buffer), + // cugraph::get_dataframe_buffer_end(output_value_buffer), + // invalid_value); if (multi_gpu) { auto& comm = handle.get_comms(); @@ -264,6 +273,8 @@ struct lookup_container_t::lookup_container_imp raft::update_host( h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); + handle.sync_stream(); + for (size_t idx = 0; idx < h_unique_types.size(); idx++) { auto typ = h_unique_types[idx]; @@ -279,13 +290,13 @@ struct lookup_container_t::lookup_container_imp auto value_buffer_typ = src_dst_from_edge_id_and_type( handle, raft::device_span{tmp_edge_ids_begin, span_size}, typ, multi_gpu); - if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { - thrust::copy(handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin(value_buffer_typ), - cugraph::get_dataframe_buffer_end(value_buffer_typ), - cugraph::get_dataframe_buffer_begin(output_value_buffer) + - h_type_offsets[typ_to_local_idx_map[typ]]); - } + // if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { + thrust::copy(handle.get_thrust_policy(), + cugraph::get_dataframe_buffer_begin(value_buffer_typ), + cugraph::get_dataframe_buffer_end(value_buffer_typ), + cugraph::get_dataframe_buffer_begin(output_value_buffer) + + h_type_offsets[typ_to_local_idx_map[typ]]); + // } } thrust::sort_by_key(handle.get_thrust_policy(), @@ -304,6 +315,7 @@ struct lookup_container_t::lookup_container_imp cugraph::kv_store_t>; using store_t = typename container_t::mapped_type; container_t edge_type_to_kv_store; + edge_type_t empty_type_ = std::numeric_limits::max() - 1; }; template @@ -336,8 +348,7 @@ void lookup_container_t::insert( raft::handle_t const& handle, edge_type_t type, raft::device_span edge_ids_to_insert, - decltype(cugraph::allocate_dataframe_buffer(0, - rmm::cuda_stream_view{}))&& values_to_insert) + dataframe_buffer_type_t&& values_to_insert) { pimpl->insert(handle, type, edge_ids_to_insert, std::move(values_to_insert)); } @@ -390,6 +401,7 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku constexpr bool multi_gpu = GraphViewType::is_multi_gpu; static_assert(std::is_integral_v); static_assert(std::is_integral_v); + static_assert(std::is_same_v); static_assert(std::is_same_v>); static_assert( @@ -400,391 +412,153 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku std::is_same_v, "edge_id_t must match with typename EdgeTypeAndIdToSrcDstLookupContainerType::edge_id_type"); - std::vector h_types_to_this_gpu{}; - std::vector h_freq_of_types_to_this_gpu{}; - std::unordered_map edge_type_to_count_map{}; - - for (size_t local_ep_idx = 0; local_ep_idx < graph_view.number_of_local_edge_partitions(); - ++local_ep_idx) { - // - // Copy edge ids and types - // + rmm::device_uvector unique_types(0, handle.get_stream()); + rmm::device_uvector unique_type_counts(0, handle.get_stream()); - auto number_of_edges_partition = - graph_view.local_edge_partition_view(local_ep_idx).number_of_edges(); - auto number_of_active_edges_partition = number_of_edges_partition; - - if (graph_view.has_edge_mask()) { - number_of_active_edges_partition = - detail::count_set_bits(handle, - (*(graph_view.edge_mask_view())).value_firsts()[local_ep_idx], - number_of_edges_partition); - } - - [[maybe_unused]] auto edgelist_ids = - rmm::device_uvector(number_of_active_edges_partition, handle.get_stream()); - - auto edgelist_types = - rmm::device_uvector(number_of_active_edges_partition, handle.get_stream()); - - auto edge_partition_mask_view = - graph_view.has_edge_mask() - ? std::make_optional< - detail::edge_partition_edge_property_device_view_t>( - *(graph_view.edge_mask_view()), local_ep_idx) - : std::nullopt; - - if (edge_partition_mask_view) { - if constexpr (multi_gpu) { - detail::copy_if_mask_set( - handle, - edge_id_view.value_firsts()[local_ep_idx], - edge_id_view.value_firsts()[local_ep_idx] + number_of_edges_partition, - (*edge_partition_mask_view).value_first(), - edgelist_ids.begin()); - } - detail::copy_if_mask_set( + if constexpr (multi_gpu) { + auto& comm = handle.get_comms(); + auto const comm_size = comm.get_size(); + auto& major_comm = handle.get_subcomm(cugraph::partition_manager::major_comm_name()); + auto const major_comm_size = major_comm.get_size(); + auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); + auto const minor_comm_size = minor_comm.get_size(); + + auto [gpu_ids, edge_types] = + cugraph::extract_transform_e( handle, - edge_type_view.value_firsts()[local_ep_idx], - edge_type_view.value_firsts()[local_ep_idx] + number_of_edges_partition, - (*edge_partition_mask_view).value_first(), - edgelist_types.begin()); - - } else { - if constexpr (multi_gpu) { - thrust::copy(handle.get_thrust_policy(), - edge_id_view.value_firsts()[local_ep_idx], - edge_id_view.value_firsts()[local_ep_idx] + number_of_edges_partition, - edgelist_ids.begin()); - } - thrust::copy(handle.get_thrust_policy(), - edge_type_view.value_firsts()[local_ep_idx], - edge_type_view.value_firsts()[local_ep_idx] + number_of_edges_partition, - edgelist_types.begin()); - } - - std::vector h_unique_gpu_ids{}; - std::vector h_gpu_offsets{}; - - if constexpr (multi_gpu) { - // - // Count number of edge ids mapped to each GPU - // - - auto& comm = handle.get_comms(); - auto const comm_size = comm.get_size(); - auto& major_comm = handle.get_subcomm(cugraph::partition_manager::major_comm_name()); - auto const major_comm_size = major_comm.get_size(); - auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); - auto const minor_comm_size = minor_comm.get_size(); - - // destination gpu id from edge id. NB: edgelist_ids will holds gpu ids after the following - // thrust::transform - thrust::transform(handle.get_thrust_policy(), - edgelist_ids.begin(), - edgelist_ids.end(), - edgelist_ids.begin(), - [key_func = cugraph::detail::compute_gpu_id_from_ext_vertex_t{ - comm_size, major_comm_size, minor_comm_size}] __device__(auto eid) { - return key_func(eid); - }); - - thrust::sort( - handle.get_thrust_policy(), - thrust::make_zip_iterator(thrust::make_tuple(edgelist_ids.begin(), edgelist_types.begin())), - thrust::make_zip_iterator(thrust::make_tuple(edgelist_ids.end(), edgelist_types.end()))); - - auto nr_unique_gpu_ids = - thrust::count_if(handle.get_thrust_policy(), - thrust::make_counting_iterator(size_t{0}), - thrust::make_counting_iterator(edgelist_ids.size()), - detail::is_first_in_run_t{edgelist_ids.data()}); - - rmm::device_uvector unique_gpu_ids(nr_unique_gpu_ids, handle.get_stream()); - rmm::device_uvector gpu_offsets(nr_unique_gpu_ids + 1, handle.get_stream()); - - thrust::fill(handle.get_thrust_policy(), gpu_offsets.begin(), gpu_offsets.end(), edge_t{0}); - - thrust::reduce_by_key(handle.get_thrust_policy(), - edgelist_ids.begin(), - edgelist_ids.end(), - thrust::make_constant_iterator(size_t{1}), - unique_gpu_ids.begin(), - gpu_offsets.begin()); - - thrust::exclusive_scan(handle.get_thrust_policy(), - gpu_offsets.begin(), - gpu_offsets.end(), - gpu_offsets.begin(), - size_t{0}); - - h_unique_gpu_ids.resize(unique_gpu_ids.size()); - h_gpu_offsets.resize(gpu_offsets.size()); - raft::update_host( - h_unique_gpu_ids.data(), unique_gpu_ids.data(), unique_gpu_ids.size(), handle.get_stream()); - raft::update_host( - h_gpu_offsets.data(), gpu_offsets.data(), gpu_offsets.size(), handle.get_stream()); + graph_view, + cugraph::edge_src_dummy_property_t{}.view(), + cugraph::edge_dst_dummy_property_t{}.view(), + view_concat(edge_id_view, edge_type_view), + cuda::proclaim_return_type>>( + [key_func = + cugraph::detail::compute_gpu_id_from_ext_edge_t{ + comm_size, + major_comm_size, + minor_comm_size}] __device__(auto, + auto, + thrust::nullopt_t, + thrust::nullopt_t, + thrust::tuple id_and_type) { + return thrust::optional>{thrust::make_tuple( + key_func(thrust::get<0>(id_and_type)), thrust::get<1>(id_and_type))}; + })); + + auto type_and_gpu_id_pair_begin = + thrust::make_zip_iterator(thrust::make_tuple(edge_types.begin(), gpu_ids.begin())); + + thrust::sort(handle.get_thrust_policy(), + type_and_gpu_id_pair_begin, + type_and_gpu_id_pair_begin + edge_types.size()); + + auto nr_unique_paris = thrust::count_if( + handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator(edge_types.size()), + detail::is_first_in_run_t{type_and_gpu_id_pair_begin}); - } else { - thrust::sort(handle.get_thrust_policy(), edgelist_types.begin(), edgelist_types.end()); + auto unique_pairs_buffer = cugraph::allocate_dataframe_buffer< + typename thrust::iterator_traits::value_type>( + nr_unique_paris, handle.get_stream()); - h_unique_gpu_ids.resize(size_t{1}); - h_unique_gpu_ids[0] = 0; + rmm::device_uvector unique_pair_counts(nr_unique_paris, handle.get_stream()); - h_gpu_offsets.resize(h_unique_gpu_ids.size() + 1); - h_gpu_offsets[0] = 0; - h_gpu_offsets[1] = edgelist_types.size(); - } + thrust::reduce_by_key(handle.get_thrust_policy(), + type_and_gpu_id_pair_begin, + type_and_gpu_id_pair_begin + edge_types.size(), + thrust::make_constant_iterator(size_t{1}), + cugraph::get_dataframe_buffer_begin(unique_pairs_buffer), + unique_pair_counts.begin()); + + edge_types.resize(0, handle.get_stream()); + gpu_ids.resize(0, handle.get_stream()); + + std::forward_as_tuple( + std::tie( + std::get<0>(unique_pairs_buffer), std::get<1>(unique_pairs_buffer), unique_pair_counts), + std::ignore) = + cugraph::groupby_gpu_id_and_shuffle_values( + handle.get_comms(), + thrust::make_zip_iterator(thrust::make_tuple(std::get<0>(unique_pairs_buffer).begin(), + std::get<1>(unique_pairs_buffer).begin(), + unique_pair_counts.begin())), + thrust::make_zip_iterator(thrust::make_tuple(std::get<0>(unique_pairs_buffer).end(), + std::get<1>(unique_pairs_buffer).end(), + unique_pair_counts.end())), + [] __device__(auto val) { return thrust::get<1>(val); }, + handle.get_stream()); // - // For edge ids mapped to each gpu, count number of unique types and elements per type. - // cub::DeviceSegmentedReduce(ByKey) ??? + // Count local #elments for all the types mapped to this GPU // - [[maybe_unused]] std::vector h_gpu_ids_partition{}; - std::vector h_types_partition{}; - std::vector h_type_freqs_partition{}; - - rmm::device_uvector unique_types_segment(0, handle.get_stream()); - rmm::device_uvector type_freqs_segment(0, handle.get_stream()); - - for (size_t idx = 0; idx < h_unique_gpu_ids.size(); ++idx) { - auto gpu_id = h_unique_gpu_ids[idx]; - - auto nr_uniqe_types_segment = thrust::count_if( - handle.get_thrust_policy(), - thrust::make_counting_iterator(size_t{0}), - thrust::make_counting_iterator( - static_cast(h_gpu_offsets[idx + 1] - h_gpu_offsets[idx])), - detail::is_first_in_run_t{edgelist_types.data() + h_gpu_offsets[idx]}); - - unique_types_segment.resize(nr_uniqe_types_segment, handle.get_stream()); - type_freqs_segment.resize(nr_uniqe_types_segment, handle.get_stream()); - - thrust::reduce_by_key(handle.get_thrust_policy(), - edgelist_types.begin() + h_gpu_offsets[idx], - edgelist_types.begin() + h_gpu_offsets[idx + 1], - thrust::make_constant_iterator(size_t{1}), - unique_types_segment.begin(), - type_freqs_segment.begin()); - - std::vector h_unique_types_segment(nr_uniqe_types_segment); - std::vector h_type_freqs_segment(nr_uniqe_types_segment); - - raft::update_host(h_unique_types_segment.data(), - unique_types_segment.data(), - unique_types_segment.size(), - handle.get_stream()); - raft::update_host(h_type_freqs_segment.data(), - type_freqs_segment.data(), - type_freqs_segment.size(), - handle.get_stream()); - - if constexpr (multi_gpu) { - h_gpu_ids_partition.insert(h_gpu_ids_partition.end(), nr_uniqe_types_segment, gpu_id); - } - - h_types_partition.insert( - h_types_partition.end(), h_unique_types_segment.begin(), h_unique_types_segment.end()); - h_type_freqs_partition.insert( - h_type_freqs_partition.end(), h_type_freqs_segment.begin(), h_type_freqs_segment.end()); - } - - [[maybe_unused]] rmm::device_uvector gpu_ids_partition(h_gpu_ids_partition.size(), - handle.get_stream()); - rmm::device_uvector types_partition(h_types_partition.size(), handle.get_stream()); - rmm::device_uvector type_freqs_partition(h_type_freqs_partition.size(), - handle.get_stream()); - - if constexpr (multi_gpu) { - raft::update_device(gpu_ids_partition.data(), - h_gpu_ids_partition.data(), - h_gpu_ids_partition.size(), - handle.get_stream()); - } - raft::update_device(types_partition.data(), - h_types_partition.data(), - h_types_partition.size(), - handle.get_stream()); - raft::update_device(type_freqs_partition.data(), - h_type_freqs_partition.data(), - h_type_freqs_partition.size(), - handle.get_stream()); + thrust::sort_by_key(handle.get_thrust_policy(), + std::get<0>(unique_pairs_buffer).begin(), + std::get<0>(unique_pairs_buffer).end(), + unique_pair_counts.begin()); - if constexpr (multi_gpu) { - // Shuffle to the proper GPUs - std::forward_as_tuple(std::tie(gpu_ids_partition, types_partition, type_freqs_partition), - std::ignore) = - cugraph::groupby_gpu_id_and_shuffle_values( - handle.get_comms(), - thrust::make_zip_iterator(thrust::make_tuple( - gpu_ids_partition.begin(), types_partition.begin(), type_freqs_partition.begin())), - thrust::make_zip_iterator(thrust::make_tuple( - gpu_ids_partition.end(), types_partition.end(), type_freqs_partition.end())), - [] __device__(auto val) { return thrust::get<0>(val); }, - handle.get_stream()); + auto nr_unique_types = thrust::count_if( + handle.get_thrust_policy(), + thrust::make_counting_iterator(size_t{0}), + thrust::make_counting_iterator(std::get<0>(unique_pairs_buffer).size()), + detail::is_first_in_run_t{std::get<0>(unique_pairs_buffer).data()}); - thrust::for_each( - handle.get_thrust_policy(), - gpu_ids_partition.begin(), - gpu_ids_partition.end(), - [rank = handle.get_comms().get_rank()] __device__(auto val) { assert(val == rank); }); - } + unique_types.resize(static_cast(nr_unique_types), handle.get_stream()); + unique_type_counts.resize(static_cast(nr_unique_types), handle.get_stream()); - thrust::sort_by_key(handle.get_thrust_policy(), - types_partition.begin(), - types_partition.end(), - type_freqs_partition.begin()); + thrust::reduce_by_key(handle.get_thrust_policy(), + std::get<0>(unique_pairs_buffer).begin(), + std::get<0>(unique_pairs_buffer).end(), + unique_pair_counts.begin(), + unique_types.begin(), + unique_type_counts.begin()); - auto nr_uniqe_types_partition = + } else { + auto edge_types = cugraph::extract_transform_e( + handle, + graph_view, + cugraph::edge_src_dummy_property_t{}.view(), + cugraph::edge_dst_dummy_property_t{}.view(), + edge_type_view, + cuda::proclaim_return_type>( + [] __device__(auto, auto, thrust::nullopt_t, thrust::nullopt_t, edge_type_t et) { + return thrust::optional{et}; + })); + + thrust::sort(handle.get_thrust_policy(), edge_types.begin(), edge_types.end()); + + auto nr_unique_types = thrust::count_if(handle.get_thrust_policy(), thrust::make_counting_iterator(size_t{0}), - thrust::make_counting_iterator(types_partition.size()), - detail::is_first_in_run_t{types_partition.data()}); + thrust::make_counting_iterator(edge_types.size()), + detail::is_first_in_run_t{edge_types.data()}); - rmm::device_uvector unique_types_partition(nr_uniqe_types_partition, - handle.get_stream()); - rmm::device_uvector unique_type_freqs_partition(nr_uniqe_types_partition, - handle.get_stream()); + unique_types.resize(static_cast(nr_unique_types), handle.get_stream()); + unique_type_counts.resize(static_cast(nr_unique_types), handle.get_stream()); thrust::reduce_by_key(handle.get_thrust_policy(), - types_partition.begin(), - types_partition.end(), - type_freqs_partition.begin(), - unique_types_partition.begin(), - unique_type_freqs_partition.begin()); - - std::vector h_unique_types_partition(nr_uniqe_types_partition); - std::vector h_unique_type_freqs_partition(nr_uniqe_types_partition); - - raft::update_host(h_unique_types_partition.data(), - unique_types_partition.data(), - unique_types_partition.size(), - handle.get_stream()); - - raft::update_host(h_unique_type_freqs_partition.data(), - unique_type_freqs_partition.data(), - unique_type_freqs_partition.size(), - handle.get_stream()); - - for (edge_type_t idx = 0; idx < nr_uniqe_types_partition; idx++) { - auto typ = h_unique_types_partition[idx]; - auto freq = h_unique_type_freqs_partition[idx]; - if (edge_type_to_count_map.find(typ) != edge_type_to_count_map.end()) { - edge_type_to_count_map[typ] += freq; - } else { - edge_type_to_count_map[typ] = freq; - } - } - - h_types_to_this_gpu.insert( - h_types_to_this_gpu.end(), h_unique_types_partition.begin(), h_unique_types_partition.end()); - - h_freq_of_types_to_this_gpu.insert(h_freq_of_types_to_this_gpu.end(), - h_unique_type_freqs_partition.begin(), - h_unique_type_freqs_partition.end()); + edge_types.begin(), + edge_types.end(), + thrust::make_constant_iterator(size_t{1}), + unique_types.begin(), + unique_type_counts.begin()); } - // - // Find global unique types and their frequencies - // - rmm::device_uvector types_to_this_gpu(h_types_to_this_gpu.size(), - handle.get_stream()); - - rmm::device_uvector freq_of_types_to_this_gpu(h_freq_of_types_to_this_gpu.size(), - handle.get_stream()); - - raft::update_device(types_to_this_gpu.data(), - h_types_to_this_gpu.data(), - h_types_to_this_gpu.size(), - handle.get_stream()); - - raft::update_device(freq_of_types_to_this_gpu.data(), - h_freq_of_types_to_this_gpu.data(), - h_freq_of_types_to_this_gpu.size(), - handle.get_stream()); - - thrust::sort_by_key(handle.get_thrust_policy(), - types_to_this_gpu.begin(), - types_to_this_gpu.end(), - freq_of_types_to_this_gpu.begin()); - - auto nr_unique_types_this_gpu = - thrust::count_if(handle.get_thrust_policy(), - thrust::make_counting_iterator(size_t{0}), - thrust::make_counting_iterator(types_to_this_gpu.size()), - detail::is_first_in_run_t{types_to_this_gpu.data()}); - - rmm::device_uvector unique_types_to_this_gpu(nr_unique_types_this_gpu, - handle.get_stream()); - rmm::device_uvector freq_of_unique_types_this_gpu(nr_unique_types_this_gpu, - handle.get_stream()); - - thrust::reduce_by_key(handle.get_thrust_policy(), - types_to_this_gpu.begin(), - types_to_this_gpu.end(), - freq_of_types_to_this_gpu.begin(), - unique_types_to_this_gpu.begin(), - freq_of_unique_types_this_gpu.begin()); - - rmm::device_uvector global_unique_types(nr_unique_types_this_gpu, - handle.get_stream()); - - thrust::transform(handle.get_thrust_policy(), - unique_types_to_this_gpu.begin(), - unique_types_to_this_gpu.end(), - global_unique_types.begin(), - [] __device__(auto val) { return int{val}; }); - - auto nr_unique_types_global = nr_unique_types_this_gpu; - - if constexpr (multi_gpu) { - global_unique_types = cugraph::detail::shuffle_ext_vertices_to_local_gpu_by_vertex_partitioning( - handle, std::move(global_unique_types)); - - thrust::sort( - handle.get_thrust_policy(), global_unique_types.begin(), global_unique_types.end()); - - auto nr_unique_elements = static_cast(thrust::distance( - global_unique_types.begin(), - thrust::unique( - handle.get_thrust_policy(), global_unique_types.begin(), global_unique_types.end()))); - - global_unique_types.resize(nr_unique_elements, handle.get_stream()); + std::vector h_unique_types(unique_types.size()); + std::vector h_unique_type_counts(unique_types.size()); - nr_unique_types_global = host_scalar_allreduce( - handle.get_comms(), nr_unique_elements, raft::comms::op_t::SUM, handle.get_stream()); - - global_unique_types = detail::device_allgatherv( - handle, - handle.get_comms(), - raft::device_span{global_unique_types.data(), global_unique_types.size()}); - - assert(global_unique_types.size() == nr_unique_types_global); - } + raft::update_host( + h_unique_types.data(), unique_types.data(), unique_types.size(), handle.get_stream()); - std::vector h_unique_types_global(nr_unique_types_global); - - raft::update_host(h_unique_types_global.data(), - global_unique_types.data(), - global_unique_types.size(), + raft::update_host(h_unique_type_counts.data(), + unique_type_counts.data(), + unique_type_counts.size(), handle.get_stream()); - // - // Create search container with appropriate capacity - // - - std::vector local_freqs(h_unique_types_global.size(), 0); - - for (size_t idx = 0; idx < h_unique_types_global.size(); idx++) { - auto typ = h_unique_types_global[idx]; - auto search_itr = edge_type_to_count_map.find(typ); - size_t store_capacity = (search_itr != edge_type_to_count_map.end()) ? search_itr->second : 0; - local_freqs[idx] = store_capacity; - } + handle.sync_stream(); auto search_container = - EdgeTypeAndIdToSrcDstLookupContainerType(handle, h_unique_types_global, local_freqs); + EdgeTypeAndIdToSrcDstLookupContainerType(handle, h_unique_types, h_unique_type_counts); // // Populate the search container @@ -860,7 +634,7 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku edgelist_ids.end(), edgelist_types.end())), [key_func = - cugraph::detail::compute_gpu_id_from_ext_vertex_t{ + cugraph::detail::compute_gpu_id_from_ext_edge_t{ comm_size, major_comm_size, minor_comm_size}] __device__(auto val) { return key_func(thrust::get<2>(val)); }, @@ -911,6 +685,7 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku raft::update_host( h_type_offsets.data(), type_offsets.data(), type_offsets.size(), handle.get_stream()); + handle.sync_stream(); for (size_t idx = 0; idx < h_unique_types.size(); idx++) { auto typ = h_unique_types[idx]; diff --git a/cpp/src/lookup/lookup_src_dst_mg.cu b/cpp/src/lookup/lookup_src_dst_mg.cu index 59072b818a7..a84d06734b9 100644 --- a/cpp/src/lookup/lookup_src_dst_mg.cu +++ b/cpp/src/lookup/lookup_src_dst_mg.cu @@ -19,8 +19,8 @@ namespace cugraph { template class lookup_container_t>; -template class lookup_container_t>; -template class lookup_container_t>; +// template class lookup_container_t>; +// template class lookup_container_t>; template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( @@ -42,7 +42,7 @@ lookup_endpoints_for_edge_ids_and_types( lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); - +/* template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, @@ -84,5 +84,5 @@ lookup_endpoints_for_edge_ids_and_types( lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); - +*/ } // namespace cugraph diff --git a/cpp/src/lookup/lookup_src_dst_sg.cu b/cpp/src/lookup/lookup_src_dst_sg.cu index 1c4d4e37d64..c901408b742 100644 --- a/cpp/src/lookup/lookup_src_dst_sg.cu +++ b/cpp/src/lookup/lookup_src_dst_sg.cu @@ -19,8 +19,8 @@ namespace cugraph { template class lookup_container_t>; -template class lookup_container_t>; -template class lookup_container_t>; +// template class lookup_container_t>; +// template class lookup_container_t>; template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( @@ -42,7 +42,7 @@ lookup_endpoints_for_edge_ids_and_types( lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); - +/* template lookup_container_t> build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, @@ -83,5 +83,6 @@ lookup_endpoints_for_edge_ids_and_types( lookup_container_t> const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); + */ } // namespace cugraph diff --git a/cpp/tests/community/mg_weighted_matching_test.cpp b/cpp/tests/community/mg_weighted_matching_test.cpp index 4f36ee36902..f4477c5b02d 100644 --- a/cpp/tests/community/mg_weighted_matching_test.cpp +++ b/cpp/tests/community/mg_weighted_matching_test.cpp @@ -69,7 +69,7 @@ class Tests_MGWeightedMatching constexpr bool multi_gpu = true; - bool test_weighted = true; + bool test_weighted = false; bool renumber = true; bool drop_self_loops = false; bool drop_multi_edges = false; @@ -97,6 +97,26 @@ class Tests_MGWeightedMatching auto mg_edge_weight_view = mg_edge_weights ? std::make_optional((*mg_edge_weights).view()) : std::nullopt; + // + CUGRAPH_EXPECTS(mg_edge_weight_view.has_value(), "Graph must be weighted"); + + auto const comm_rank = handle_->get_comms().get_rank(); + for (size_t ep_idx = 0; ep_idx < mg_graph_view.number_of_local_edge_partitions(); ++ep_idx) { + raft::device_span weights_of_edges_stored_in_this_edge_partition{}; + + auto value_firsts = mg_edge_weight_view->value_firsts(); + auto edge_counts = mg_edge_weight_view->edge_counts(); + + RAFT_CUDA_TRY(cudaDeviceSynchronize()); + auto weights_title = std::string("weights_") + .append(std::to_string(comm_rank)) + .append("_") + .append(std::to_string(ep_idx)); + raft::print_device_vector( + weights_title.c_str(), value_firsts[ep_idx], edge_counts[ep_idx], std::cout); + } + + // std::optional> edge_mask{std::nullopt}; if (weighted_matching_usecase.edge_masking) { edge_mask = cugraph::test::generate::edge_property( @@ -107,10 +127,22 @@ class Tests_MGWeightedMatching rmm::device_uvector mg_partners(0, handle_->get_stream()); weight_t mg_matching_weights; + if (cugraph::test::g_perf) { + RAFT_CUDA_TRY(cudaDeviceSynchronize()); // for consistent performance measurement + handle_->get_comms().barrier(); + hr_timer.start("MG approximate_weighted_matching"); + } + std::forward_as_tuple(mg_partners, mg_matching_weights) = cugraph::approximate_weighted_matching( *handle_, mg_graph_view, (*mg_edge_weights).view()); + if (cugraph::test::g_perf) { + RAFT_CUDA_TRY(cudaDeviceSynchronize()); // for consistent performance measurement + handle_->get_comms().barrier(); + hr_timer.stop(); + hr_timer.display_and_clear(std::cout); + } if (weighted_matching_usecase.check_correctness) { auto h_mg_partners = cugraph::test::to_host(*handle_, mg_partners); diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp index 35312878e83..99a08d30d85 100644 --- a/cpp/tests/lookup/lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -39,7 +39,7 @@ #include struct EdgeSrcDstLookup_UseCase { - bool edge_masking{false}; + // FIXME: Test with edge mask once the graph generator is updated to generate edge ids and types bool check_correctness{true}; }; @@ -93,11 +93,6 @@ class Tests_SGLookupEdgeSrcDst sg_edge_weights ? std::make_optional((*sg_edge_weights).view()) : std::nullopt; std::optional> edge_mask{std::nullopt}; - if (lookup_usecase.edge_masking) { - edge_mask = cugraph::test::generate::edge_property( - handle, sg_graph_view, 2); - // sg_graph_view.attach_edge_mask((*edge_mask).view()); - } // // FIXME: As the graph generator doesn't generate edge ids and types at the moment, generate @@ -106,7 +101,7 @@ class Tests_SGLookupEdgeSrcDst // int32_t number_of_edge_types = - 6 + static_cast(sg_graph_view.number_of_vertices() / (1 << 10)); + 1 + (std::rand() % (1 + (sg_graph_view.number_of_vertices() / (1 << 10)))); std::optional> edge_types{ std::nullopt}; @@ -245,26 +240,26 @@ class Tests_SGLookupEdgeSrcDst } }; -using Tests_SGLookupEdgeSrcDst_File = Tests_SGLookupEdgeSrcDst; +// using Tests_SGLookupEdgeSrcDst_File = Tests_SGLookupEdgeSrcDst; using Tests_SGLookupEdgeSrcDst_Rmat = Tests_SGLookupEdgeSrcDst; -TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) -{ - run_current_test( - override_File_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) +// { +// run_current_test( +// override_File_Usecase_with_cmd_line_arguments(GetParam())); +// } -TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) -{ - run_current_test( - override_File_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) +// { +// run_current_test( +// override_File_Usecase_with_cmd_line_arguments(GetParam())); +// } -TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) -{ - run_current_test( - override_File_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) +// { +// run_current_test( +// override_File_Usecase_with_cmd_line_arguments(GetParam())); +// } TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) { @@ -272,31 +267,27 @@ TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); } -TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) -{ - run_current_test( - override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) +// { +// run_current_test( +// override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +// } -TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) -{ - run_current_test( - override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) +// { +// run_current_test( +// override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +// } -INSTANTIATE_TEST_SUITE_P( - file_test, - Tests_SGLookupEdgeSrcDst_File, - ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{false} - // , EdgeSrcDstLookup_UseCase{true} - ), - ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); +// INSTANTIATE_TEST_SUITE_P( +// file_test, +// Tests_SGLookupEdgeSrcDst_File, +// ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{}), +// ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); INSTANTIATE_TEST_SUITE_P(rmat_small_test, Tests_SGLookupEdgeSrcDst_Rmat, - ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{false} - // , EdgeSrcDstLookup_UseCase{true} - ), + ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{}), ::testing::Values(cugraph::test::Rmat_Usecase( 3, 3, 0.57, 0.19, 0.19, 0, true, false)))); @@ -308,9 +299,7 @@ INSTANTIATE_TEST_SUITE_P( factor (to avoid running same benchmarks more than once) */ Tests_SGLookupEdgeSrcDst_Rmat, ::testing::Combine( - ::testing::Values(EdgeSrcDstLookup_UseCase{false, false} - // , EdgeSrcDstLookup_UseCase{true, false} - ), + ::testing::Values(EdgeSrcDstLookup_UseCase{false}), ::testing::Values(cugraph::test::Rmat_Usecase(20, 32, 0.57, 0.19, 0.19, 0, false, false)))); CUGRAPH_TEST_PROGRAM_MAIN() diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp index 0bbf32525ff..e940b1935ce 100644 --- a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -41,7 +41,7 @@ #include struct EdgeSrcDstLookup_UseCase { - bool edge_masking{false}; + // FIXME: Test with edge mask once the graph generator is updated to generate edge ids and types bool check_correctness{true}; }; @@ -101,11 +101,6 @@ class Tests_MGLookupEdgeSrcDst mg_edge_weights ? std::make_optional((*mg_edge_weights).view()) : std::nullopt; std::optional> edge_mask{std::nullopt}; - if (lookup_usecase.edge_masking) { - edge_mask = cugraph::test::generate::edge_property( - *handle_, mg_graph_view, 2); - // mg_graph_view.attach_edge_mask((*edge_mask).view()); - } // // FIXME: As the graph generator doesn't generate edge ids and types at the moment, generate @@ -114,7 +109,7 @@ class Tests_MGLookupEdgeSrcDst // int32_t number_of_edge_types = - 6 + static_cast(mg_graph_view.number_of_vertices() / (1 << 10)); + 1 + (std::rand() % (1 + (mg_graph_view.number_of_vertices() / (1 << 10)))); std::optional> edge_types{ std::nullopt}; @@ -275,26 +270,26 @@ class Tests_MGLookupEdgeSrcDst template std::unique_ptr Tests_MGLookupEdgeSrcDst::handle_ = nullptr; -using Tests_MGLookupEdgeSrcDst_File = Tests_MGLookupEdgeSrcDst; +// using Tests_MGLookupEdgeSrcDst_File = Tests_MGLookupEdgeSrcDst; using Tests_MGLookupEdgeSrcDst_Rmat = Tests_MGLookupEdgeSrcDst; -TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) -{ - run_current_test( - override_File_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) +// { +// run_current_test( +// override_File_Usecase_with_cmd_line_arguments(GetParam())); +// } -TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) -{ - run_current_test( - override_File_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) +// { +// run_current_test( +// override_File_Usecase_with_cmd_line_arguments(GetParam())); +// } -TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) -{ - run_current_test( - override_File_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) +// { +// run_current_test( +// override_File_Usecase_with_cmd_line_arguments(GetParam())); +// } TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) { @@ -302,31 +297,27 @@ TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); } -TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) -{ - run_current_test( - override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) +// { +// run_current_test( +// override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +// } -TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) -{ - run_current_test( - override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); -} +// TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) +// { +// run_current_test( +// override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +// } -INSTANTIATE_TEST_SUITE_P( - file_test, - Tests_MGLookupEdgeSrcDst_File, - ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{false} - // , EdgeSrcDstLookup_UseCase{true} - ), - ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); +// INSTANTIATE_TEST_SUITE_P( +// file_test, +// Tests_MGLookupEdgeSrcDst_File, +// ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{}), +// ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); INSTANTIATE_TEST_SUITE_P(rmat_small_test, Tests_MGLookupEdgeSrcDst_Rmat, - ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{false} - // , EdgeSrcDstLookup_UseCase{true} - ), + ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{}), ::testing::Values(cugraph::test::Rmat_Usecase( 3, 2, 0.57, 0.19, 0.19, 0, true, false)))); @@ -338,9 +329,7 @@ INSTANTIATE_TEST_SUITE_P( factor (to avoid running same benchmarks more than once) */ Tests_MGLookupEdgeSrcDst_Rmat, ::testing::Combine( - ::testing::Values(EdgeSrcDstLookup_UseCase{false, false} - // , EdgeSrcDstLookup_UseCase{true, false} - ), + ::testing::Values(EdgeSrcDstLookup_UseCase{false}), ::testing::Values(cugraph::test::Rmat_Usecase(5, 32, 0.57, 0.19, 0.19, 0, true, false)))); CUGRAPH_MG_TEST_PROGRAM_MAIN() From 60af60ab3412a4d000297fe4211c6b0e871322a2 Mon Sep 17 00:00:00 2001 From: Naim Date: Tue, 4 Jun 2024 20:16:33 +0200 Subject: [PATCH 15/26] Add vertex_t as template param and value_t as optional template param --- cpp/include/cugraph/sampling_functions.hpp | 13 +- .../cugraph/src_dst_lookup_container.hpp | 26 +--- cpp/src/lookup/lookup_src_dst_impl.cuh | 111 +++++++----------- cpp/src/lookup/lookup_src_dst_mg.cu | 43 ++++--- cpp/src/lookup/lookup_src_dst_sg.cu | 42 +++---- cpp/tests/lookup/lookup_src_dst_test.cpp | 2 +- cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 2 +- 7 files changed, 93 insertions(+), 146 deletions(-) diff --git a/cpp/include/cugraph/sampling_functions.hpp b/cpp/include/cugraph/sampling_functions.hpp index c7ff74f93f0..ed4ca9bc3ff 100644 --- a/cpp/include/cugraph/sampling_functions.hpp +++ b/cpp/include/cugraph/sampling_functions.hpp @@ -336,8 +336,7 @@ sort_sampled_edgelist(raft::handle_t const& handle, * source and destination lookup map. */ template -lookup_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( +lookup_container_t build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_id_view, @@ -364,10 +363,9 @@ build_edge_id_and_type_to_src_dst_lookup_map( */ template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t> const& - search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup); @@ -394,10 +392,9 @@ lookup_endpoints_for_edge_ids_of_single_type( */ template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t> const& - search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index 9e0ca1a8c4e..8e8595ae929 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -31,28 +31,14 @@ namespace cugraph { -namespace detail { - -template -constexpr TupleType invalid_of_thrust_tuple_of_integral(std::index_sequence) -{ - return thrust::make_tuple( - cugraph::invalid_idx::type>::value...); -} -} // namespace detail - -template -constexpr TupleType invalid_of_thrust_tuple_of_integral() -{ - return detail::invalid_of_thrust_tuple_of_integral( - std::make_index_sequence::value>()); -} - -template +template > class lookup_container_t { - template + template struct lookup_container_impl; - std::unique_ptr> pimpl; + std::unique_ptr> pimpl; public: using edge_id_type = edge_id_t; diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index 4b041273c76..319c136fb56 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -31,9 +31,9 @@ namespace cugraph { -template -template -struct lookup_container_t::lookup_container_impl { +template +template +struct lookup_container_t::lookup_container_impl { static_assert(std::is_integral_v); static_assert(std::is_integral_v); @@ -47,8 +47,8 @@ struct lookup_container_t::lookup_container_imp std::vector types, std::vector type_counts) { - auto invalid_key = cugraph::invalid_vertex_id::value; - auto invalid_value = invalid_of_thrust_tuple_of_integral(); + auto invalid_vertex_id = cugraph::invalid_vertex_id::value; + auto invalid_value = thrust::tuple(invalid_vertex_id, invalid_vertex_id); edge_type_to_kv_store = container_t{}; edge_type_to_kv_store.reserve(types.size()); @@ -59,11 +59,11 @@ struct lookup_container_t::lookup_container_imp size_t store_capacity = type_counts[idx]; edge_type_to_kv_store.insert( - {typ, store_t(store_capacity, invalid_key, invalid_value, handle.get_stream())}); + {typ, store_t(store_capacity, invalid_vertex_id, invalid_value, handle.get_stream())}); } edge_type_to_kv_store.insert( - {empty_type_, store_t(0, invalid_key, invalid_value, handle.get_stream())}); + {empty_type_, store_t(0, invalid_vertex_id, invalid_value, handle.get_stream())}); } void insert(raft::handle_t const& handle, @@ -103,28 +103,9 @@ struct lookup_container_t::lookup_container_imp kv_store_object = &(itr->second); } else { - // edge_type_t type_with_no_edges = std::numeric_limits::max() - 1; kv_store_object = &(edge_type_to_kv_store.find(empty_type_)->second); } - /* - else { - cugraph::resize_dataframe_buffer( - value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); - - auto invalid_value = invalid_of_thrust_tuple_of_integral(); - - thrust::fill(handle.get_thrust_policy(), - cugraph::get_dataframe_buffer_begin(value_buffer), - cugraph::get_dataframe_buffer_end(value_buffer), - invalid_value); - - // FIXME: we are assuming value_t is tuple of size 2 - return std::make_tuple(std::move(std::get<0>(value_buffer)), - std::move(std::get<1>(value_buffer))); - } - */ - if (multi_gpu) { auto& comm = handle.get_comms(); auto const comm_size = comm.get_size(); @@ -150,7 +131,6 @@ struct lookup_container_t::lookup_container_imp handle.get_stream()); } - // FIXME: we are assuming value_t is tuple of size 2 return std::make_tuple(std::move(std::get<0>(value_buffer)), std::move(std::get<1>(value_buffer))); } @@ -238,12 +218,6 @@ struct lookup_container_t::lookup_container_imp auto output_value_buffer = cugraph::allocate_dataframe_buffer(edge_ids_to_lookup.size(), handle.get_stream()); - // auto invalid_value = invalid_of_thrust_tuple_of_integral(); - // thrust::fill(handle.get_thrust_policy(), - // cugraph::get_dataframe_buffer_begin(output_value_buffer), - // cugraph::get_dataframe_buffer_end(output_value_buffer), - // invalid_value); - if (multi_gpu) { auto& comm = handle.get_comms(); auto rx_counts = host_scalar_allgather(comm, unique_types.size(), handle.get_stream()); @@ -290,13 +264,11 @@ struct lookup_container_t::lookup_container_imp auto value_buffer_typ = src_dst_from_edge_id_and_type( handle, raft::device_span{tmp_edge_ids_begin, span_size}, typ, multi_gpu); - // if (typ_to_local_idx_map.find(typ) != typ_to_local_idx_map.end()) { thrust::copy(handle.get_thrust_policy(), cugraph::get_dataframe_buffer_begin(value_buffer_typ), cugraph::get_dataframe_buffer_end(value_buffer_typ), cugraph::get_dataframe_buffer_begin(output_value_buffer) + h_type_offsets[typ_to_local_idx_map[typ]]); - // } } thrust::sort_by_key(handle.get_thrust_policy(), @@ -304,7 +276,6 @@ struct lookup_container_t::lookup_container_imp original_idxs.end(), cugraph::get_dataframe_buffer_begin(output_value_buffer)); - // FIXME: we are assuming value_t is tuple of size 2 return std::make_tuple(std::move(std::get<0>(output_value_buffer)), std::move(std::get<1>(output_value_buffer))); } @@ -318,33 +289,34 @@ struct lookup_container_t::lookup_container_imp edge_type_t empty_type_ = std::numeric_limits::max() - 1; }; -template -lookup_container_t::~lookup_container_t() +template +lookup_container_t::~lookup_container_t() { pimpl.reset(); } -template -lookup_container_t::lookup_container_t() - : pimpl{std::make_unique>()} +template +lookup_container_t::lookup_container_t() + : pimpl{std::make_unique>()} { } -template -lookup_container_t::lookup_container_t( +template +lookup_container_t::lookup_container_t( raft::handle_t const& handle, std::vector types, std::vector type_counts) - : pimpl{std::make_unique>( + : pimpl{std::make_unique>( handle, types, type_counts)} { } -template -lookup_container_t::lookup_container_t(const lookup_container_t&) +template +lookup_container_t::lookup_container_t( + const lookup_container_t&) { } -template -void lookup_container_t::insert( +template +void lookup_container_t::insert( raft::handle_t const& handle, edge_type_t type, raft::device_span edge_ids_to_insert, @@ -353,9 +325,9 @@ void lookup_container_t::insert( pimpl->insert(handle, type, edge_ids_to_insert, std::move(values_to_insert)); } -template +template dataframe_buffer_type_t -lookup_container_t::src_dst_from_edge_id_and_type( +lookup_container_t::src_dst_from_edge_id_and_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup, @@ -365,9 +337,9 @@ lookup_container_t::src_dst_from_edge_id_and_ty handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); } -template +template dataframe_buffer_type_t -lookup_container_t::src_dst_from_edge_id_and_type( +lookup_container_t::src_dst_from_edge_id_and_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup, @@ -697,7 +669,6 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku auto zip_itr = thrust::make_zip_iterator( thrust::make_tuple(edgelist_majors.begin(), edgelist_minors.begin())); - // FIXME: Can we avoid copying thrust::copy(handle.get_thrust_policy(), zip_itr + h_type_offsets[idx], zip_itr + h_type_offsets[idx] + nr_elements_to_insert, @@ -725,7 +696,7 @@ template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, raft::device_span edge_ids_to_lookup, @@ -756,7 +727,7 @@ template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, EdgeTypeAndIdToSrcDstLookupContainerType const& search_container, raft::device_span edge_ids_to_lookup, @@ -786,44 +757,44 @@ lookup_endpoints_for_edge_ids_and_types( template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t> const& - search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup) { - using m_t = lookup_container_t>; - return detail:: - lookup_endpoints_for_edge_ids_of_single_type( - handle, search_container, edge_ids_to_lookup, edge_type_to_lookup); + using m_t = lookup_container_t; + return detail::lookup_endpoints_from_edge_ids_and_single_type( + handle, search_container, edge_ids_to_lookup, edge_type_to_lookup); } template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t> const& - search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup) { - using m_t = lookup_container_t>; + using m_t = lookup_container_t; return detail:: - lookup_endpoints_for_edge_ids_and_types( + lookup_endpoints_from_edge_ids_and_types( handle, search_container, edge_ids_to_lookup, edge_types_to_lookup); } template -lookup_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( +lookup_container_t build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_id_view, edge_property_view_t edge_type_view) { using graph_view_t = graph_view_t; - using return_t = lookup_container_t>; + using return_t = lookup_container_t; return detail::build_edge_id_and_type_to_src_dst_lookup_map>; -// template class lookup_container_t>; -// template class lookup_container_t>; +template class lookup_container_t; +template class lookup_container_t; +template class lookup_container_t; -template lookup_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( +template lookup_container_t build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_id_view, edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -/* -template lookup_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( + +template lookup_container_t build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_id_view, edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -template lookup_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( +template lookup_container_t build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_id_view, edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -*/ + } // namespace cugraph diff --git a/cpp/src/lookup/lookup_src_dst_sg.cu b/cpp/src/lookup/lookup_src_dst_sg.cu index c901408b742..af4594cbe51 100644 --- a/cpp/src/lookup/lookup_src_dst_sg.cu +++ b/cpp/src/lookup/lookup_src_dst_sg.cu @@ -18,71 +18,67 @@ namespace cugraph { -template class lookup_container_t>; -// template class lookup_container_t>; -// template class lookup_container_t>; +template class lookup_container_t; +template class lookup_container_t; +template class lookup_container_t; -template lookup_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( +template lookup_container_t build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_id_view, edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, int32_t const edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -/* -template lookup_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( + +template lookup_container_t build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_id_view, edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); -template lookup_container_t> -build_edge_id_and_type_to_src_dst_lookup_map( +template lookup_container_t build_edge_id_and_type_to_src_dst_lookup_map( raft::handle_t const& handle, graph_view_t const& graph_view, edge_property_view_t edge_id_view, edge_property_view_t edge_type_view); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_of_single_type( +lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, int32_t edge_type_to_lookup); template std::tuple, rmm::device_uvector> -lookup_endpoints_for_edge_ids_and_types( +lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t> const& search_container, + lookup_container_t const& search_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); - */ } // namespace cugraph diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp index 99a08d30d85..fa0dd770f5a 100644 --- a/cpp/tests/lookup/lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -220,7 +220,7 @@ class Tests_SGLookupEdgeSrcDst d_mg_edge_types = cugraph::test::to_device(handle, h_mg_edge_types); auto [srcs, dsts] = - cugraph::lookup_endpoints_for_edge_ids_and_types( + cugraph::lookup_endpoints_from_edge_ids_and_types( handle, search_container, raft::device_span((*d_mg_edge_ids).begin(), (*d_mg_edge_ids).size()), diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp index e940b1935ce..8cbdde6e17c 100644 --- a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -244,7 +244,7 @@ class Tests_MGLookupEdgeSrcDst d_mg_edge_types = cugraph::test::to_device(*handle_, h_mg_edge_types); auto [srcs, dsts] = - cugraph::lookup_endpoints_for_edge_ids_and_types( + cugraph::lookup_endpoints_from_edge_ids_and_types( *handle_, search_container, raft::device_span((*d_mg_edge_ids).begin(), (*d_mg_edge_ids).size()), From 2db671e6469b866cd209ac3f09e0c64c031c878c Mon Sep 17 00:00:00 2001 From: Naim Date: Tue, 4 Jun 2024 20:28:49 +0200 Subject: [PATCH 16/26] Address aditional PR comments --- .../community/mg_weighted_matching_test.cpp | 23 ++----------------- cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 13 +++++++++++ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/cpp/tests/community/mg_weighted_matching_test.cpp b/cpp/tests/community/mg_weighted_matching_test.cpp index f4477c5b02d..8abd7646065 100644 --- a/cpp/tests/community/mg_weighted_matching_test.cpp +++ b/cpp/tests/community/mg_weighted_matching_test.cpp @@ -97,26 +97,6 @@ class Tests_MGWeightedMatching auto mg_edge_weight_view = mg_edge_weights ? std::make_optional((*mg_edge_weights).view()) : std::nullopt; - // - CUGRAPH_EXPECTS(mg_edge_weight_view.has_value(), "Graph must be weighted"); - - auto const comm_rank = handle_->get_comms().get_rank(); - for (size_t ep_idx = 0; ep_idx < mg_graph_view.number_of_local_edge_partitions(); ++ep_idx) { - raft::device_span weights_of_edges_stored_in_this_edge_partition{}; - - auto value_firsts = mg_edge_weight_view->value_firsts(); - auto edge_counts = mg_edge_weight_view->edge_counts(); - - RAFT_CUDA_TRY(cudaDeviceSynchronize()); - auto weights_title = std::string("weights_") - .append(std::to_string(comm_rank)) - .append("_") - .append(std::to_string(ep_idx)); - raft::print_device_vector( - weights_title.c_str(), value_firsts[ep_idx], edge_counts[ep_idx], std::cout); - } - - // std::optional> edge_mask{std::nullopt}; if (weighted_matching_usecase.edge_masking) { edge_mask = cugraph::test::generate::edge_property( @@ -130,7 +110,7 @@ class Tests_MGWeightedMatching if (cugraph::test::g_perf) { RAFT_CUDA_TRY(cudaDeviceSynchronize()); // for consistent performance measurement handle_->get_comms().barrier(); - hr_timer.start("MG approximate_weighted_matching"); + hr_timer.start("MG Approximate Weighted Matching"); } std::forward_as_tuple(mg_partners, mg_matching_weights) = @@ -143,6 +123,7 @@ class Tests_MGWeightedMatching hr_timer.stop(); hr_timer.display_and_clear(std::cout); } + if (weighted_matching_usecase.check_correctness) { auto h_mg_partners = cugraph::test::to_host(*handle_, mg_partners); diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp index 8cbdde6e17c..5d1153c90c9 100644 --- a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -196,10 +196,23 @@ class Tests_MGLookupEdgeSrcDst handle_->get_stream()); } + if (cugraph::test::g_perf) { + RAFT_CUDA_TRY(cudaDeviceSynchronize()); // for consistent performance measurement + handle_->get_comms().barrier(); + hr_timer.start("MG Build Lookup Map"); + } + auto search_container = cugraph::build_edge_id_and_type_to_src_dst_lookup_map( *handle_, mg_graph_view, (*edge_ids).view(), (*edge_types).view()); + if (cugraph::test::g_perf) { + RAFT_CUDA_TRY(cudaDeviceSynchronize()); // for consistent performance measurement + handle_->get_comms().barrier(); + hr_timer.stop(); + hr_timer.display_and_clear(std::cout); + } + if (lookup_usecase.check_correctness) { rmm::device_uvector d_mg_srcs(0, handle_->get_stream()); rmm::device_uvector d_mg_dsts(0, handle_->get_stream()); From 21258009e1b0eb8d52a5f6fb5a1d75b0e951623b Mon Sep 17 00:00:00 2001 From: Naim Date: Tue, 4 Jun 2024 22:04:57 +0200 Subject: [PATCH 17/26] Uncomment tests --- cpp/tests/lookup/lookup_src_dst_test.cpp | 66 ++++++++++----------- cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 66 ++++++++++----------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp index fa0dd770f5a..c31ae533218 100644 --- a/cpp/tests/lookup/lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -240,26 +240,26 @@ class Tests_SGLookupEdgeSrcDst } }; -// using Tests_SGLookupEdgeSrcDst_File = Tests_SGLookupEdgeSrcDst; +using Tests_SGLookupEdgeSrcDst_File = Tests_SGLookupEdgeSrcDst; using Tests_SGLookupEdgeSrcDst_Rmat = Tests_SGLookupEdgeSrcDst; -// TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) -// { -// run_current_test( -// override_File_Usecase_with_cmd_line_arguments(GetParam())); -// } +TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} -// TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) -// { -// run_current_test( -// override_File_Usecase_with_cmd_line_arguments(GetParam())); -// } +TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} -// TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) -// { -// run_current_test( -// override_File_Usecase_with_cmd_line_arguments(GetParam())); -// } +TEST_P(Tests_SGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) { @@ -267,23 +267,23 @@ TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); } -// TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) -// { -// run_current_test( -// override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); -// } - -// TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) -// { -// run_current_test( -// override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); -// } - -// INSTANTIATE_TEST_SUITE_P( -// file_test, -// Tests_SGLookupEdgeSrcDst_File, -// ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{}), -// ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); +TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_SGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +INSTANTIATE_TEST_SUITE_P( + file_test, + Tests_SGLookupEdgeSrcDst_File, + ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{}), + ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); INSTANTIATE_TEST_SUITE_P(rmat_small_test, Tests_SGLookupEdgeSrcDst_Rmat, diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp index 5d1153c90c9..22a5252be74 100644 --- a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -283,26 +283,26 @@ class Tests_MGLookupEdgeSrcDst template std::unique_ptr Tests_MGLookupEdgeSrcDst::handle_ = nullptr; -// using Tests_MGLookupEdgeSrcDst_File = Tests_MGLookupEdgeSrcDst; +using Tests_MGLookupEdgeSrcDst_File = Tests_MGLookupEdgeSrcDst; using Tests_MGLookupEdgeSrcDst_Rmat = Tests_MGLookupEdgeSrcDst; -// TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) -// { -// run_current_test( -// override_File_Usecase_with_cmd_line_arguments(GetParam())); -// } +TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int32FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} -// TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) -// { -// run_current_test( -// override_File_Usecase_with_cmd_line_arguments(GetParam())); -// } +TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt32Int64FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} -// TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) -// { -// run_current_test( -// override_File_Usecase_with_cmd_line_arguments(GetParam())); -// } +TEST_P(Tests_MGLookupEdgeSrcDst_File, CheckInt64Int64FloatFloat) +{ + run_current_test( + override_File_Usecase_with_cmd_line_arguments(GetParam())); +} TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) { @@ -310,23 +310,23 @@ TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int32FloatFloat) override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); } -// TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) -// { -// run_current_test( -// override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); -// } - -// TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) -// { -// run_current_test( -// override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); -// } - -// INSTANTIATE_TEST_SUITE_P( -// file_test, -// Tests_MGLookupEdgeSrcDst_File, -// ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{}), -// ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); +TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt32Int64FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +TEST_P(Tests_MGLookupEdgeSrcDst_Rmat, CheckInt64Int64FloatFloat) +{ + run_current_test( + override_Rmat_Usecase_with_cmd_line_arguments(GetParam())); +} + +INSTANTIATE_TEST_SUITE_P( + file_test, + Tests_MGLookupEdgeSrcDst_File, + ::testing::Combine(::testing::Values(EdgeSrcDstLookup_UseCase{}), + ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx")))); INSTANTIATE_TEST_SUITE_P(rmat_small_test, Tests_MGLookupEdgeSrcDst_Rmat, From 27c3646480574b04f0f3a7d2c71a82fe702fe3aa Mon Sep 17 00:00:00 2001 From: Naim Date: Thu, 6 Jun 2024 19:39:34 +0200 Subject: [PATCH 18/26] Address PR comments --- cpp/include/cugraph/sampling_functions.hpp | 8 +- .../cugraph/src_dst_lookup_container.hpp | 4 +- cpp/src/lookup/lookup_src_dst_impl.cuh | 112 +++++++++++------- cpp/tests/lookup/lookup_src_dst_test.cpp | 7 +- cpp/tests/lookup/mg_lookup_src_dst_test.cpp | 7 +- 5 files changed, 86 insertions(+), 52 deletions(-) diff --git a/cpp/include/cugraph/sampling_functions.hpp b/cpp/include/cugraph/sampling_functions.hpp index ed4ca9bc3ff..2c371a9f9d8 100644 --- a/cpp/include/cugraph/sampling_functions.hpp +++ b/cpp/include/cugraph/sampling_functions.hpp @@ -352,7 +352,7 @@ lookup_container_t build_edge_id_and_type_to_src_ * @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 search_container Object of type cugraph::lookup_container_t that encapsulates edge id and + * @param lookup_container Object of type cugraph::lookup_container_t that encapsulates edge id and * type to source and destination lookup map. * @param edge_ids_to_lookup Device span of edge ids to lookup * @param edge_type_to_lookup Type of the edges corresponding to edge ids in @p edge_ids_to_lookup @@ -365,7 +365,7 @@ template , rmm::device_uvector> lookup_endpoints_from_edge_ids_and_single_type( raft::handle_t const& handle, - lookup_container_t const& search_container, + lookup_container_t const& lookup_container, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup); @@ -379,7 +379,7 @@ lookup_endpoints_from_edge_ids_and_single_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 search_container Object of type cugraph::lookup_container_t that encapsulates edge id and + * @param lookup_container Object of type cugraph::lookup_container_t that encapsulates edge id and * type to source and destination lookup map. * @param edge_ids_to_lookup Device span of edge ids to lookup * @param edge_types_to_lookup Device span of edge types corresponding to the edge ids @@ -394,7 +394,7 @@ template , rmm::device_uvector> lookup_endpoints_from_edge_ids_and_types( raft::handle_t const& handle, - lookup_container_t const& search_container, + lookup_container_t const& lookup_container, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup); diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index 8e8595ae929..4b1509f0367 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -61,13 +61,13 @@ class lookup_container_t { raft::device_span edge_ids_to_insert, dataframe_buffer_type_t&& values_to_insert); - dataframe_buffer_type_t src_dst_from_edge_id_and_type( + dataframe_buffer_type_t lookup_from_edge_ids_and_single_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup, bool multi_gpu) const; - dataframe_buffer_type_t src_dst_from_edge_id_and_type( + dataframe_buffer_type_t lookup_from_edge_ids_and_types( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup, diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index 319c136fb56..8b04da92ef2 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -181,24 +181,23 @@ struct lookup_container_t::lookup_con rmm::device_uvector unique_types(nr_uniqe_edge_types_to_lookup, handle.get_stream()); - rmm::device_uvector type_offsets(nr_uniqe_edge_types_to_lookup + 1, + rmm::device_uvector type_offsets(nr_uniqe_edge_types_to_lookup + size_t{1}, handle.get_stream()); - thrust::fill( - handle.get_thrust_policy(), type_offsets.begin(), type_offsets.end(), edge_id_t{0}); + thrust::copy_if(handle.get_thrust_policy(), + tmp_edge_types_to_lookup.begin(), + tmp_edge_types_to_lookup.end(), + thrust::make_counting_iterator(size_t{0}), + unique_types.begin(), + detail::is_first_in_run_t{tmp_edge_types_to_lookup.data()}); - thrust::reduce_by_key(handle.get_thrust_policy(), - tmp_edge_types_to_lookup.begin(), - tmp_edge_types_to_lookup.end(), - thrust::make_constant_iterator(size_t{1}), - unique_types.begin(), - type_offsets.begin()); - - thrust::exclusive_scan(handle.get_thrust_policy(), - type_offsets.begin(), - type_offsets.end(), - type_offsets.begin(), - size_t{0}); + type_offsets.set_element_to_zero_async(0, handle.get_stream()); + thrust::upper_bound(handle.get_thrust_policy(), + tmp_edge_types_to_lookup.begin(), + tmp_edge_types_to_lookup.end(), + unique_types.begin(), + unique_types.end(), + type_offsets.begin() + 1); std::vector h_unique_types(unique_types.size()); std::vector h_type_offsets(type_offsets.size()); @@ -327,7 +326,7 @@ void lookup_container_t::insert( template dataframe_buffer_type_t -lookup_container_t::src_dst_from_edge_id_and_type( +lookup_container_t::lookup_from_edge_ids_and_single_type( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, edge_type_t edge_type_to_lookup, @@ -339,7 +338,7 @@ lookup_container_t::src_dst_from_edge template dataframe_buffer_type_t -lookup_container_t::src_dst_from_edge_id_and_type( +lookup_container_t::lookup_from_edge_ids_and_types( raft::handle_t const& handle, raft::device_span edge_ids_to_lookup, raft::device_span edge_types_to_lookup, @@ -435,20 +434,37 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku rmm::device_uvector unique_pair_counts(nr_unique_paris, handle.get_stream()); - thrust::reduce_by_key(handle.get_thrust_policy(), + { + rmm::device_uvector unique_pair_end_offsets(nr_unique_paris, handle.get_stream()); + + thrust::copy_if(handle.get_thrust_policy(), + type_and_gpu_id_pair_begin, + type_and_gpu_id_pair_begin + edge_types.size(), + thrust::make_counting_iterator(size_t{0}), + cugraph::get_dataframe_buffer_begin(unique_pairs_buffer), + detail::is_first_in_run_t{ + type_and_gpu_id_pair_begin}); + + thrust::upper_bound(handle.get_thrust_policy(), type_and_gpu_id_pair_begin, type_and_gpu_id_pair_begin + edge_types.size(), - thrust::make_constant_iterator(size_t{1}), cugraph::get_dataframe_buffer_begin(unique_pairs_buffer), - unique_pair_counts.begin()); + cugraph::get_dataframe_buffer_end(unique_pairs_buffer), + unique_pair_end_offsets.begin()); + + thrust::adjacent_difference(handle.get_thrust_policy(), + unique_pair_end_offsets.begin(), + unique_pair_end_offsets.end(), + unique_pair_counts.begin()); + } edge_types.resize(0, handle.get_stream()); gpu_ids.resize(0, handle.get_stream()); + edge_types.shrink_to_fit(handle.get_stream()); + gpu_ids.shrink_to_fit(handle.get_stream()); std::forward_as_tuple( - std::tie( - std::get<0>(unique_pairs_buffer), std::get<1>(unique_pairs_buffer), unique_pair_counts), - std::ignore) = + std::tie(std::get<0>(unique_pairs_buffer), std::ignore, unique_pair_counts), std::ignore) = cugraph::groupby_gpu_id_and_shuffle_values( handle.get_comms(), thrust::make_zip_iterator(thrust::make_tuple(std::get<0>(unique_pairs_buffer).begin(), @@ -508,12 +524,27 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku unique_types.resize(static_cast(nr_unique_types), handle.get_stream()); unique_type_counts.resize(static_cast(nr_unique_types), handle.get_stream()); - thrust::reduce_by_key(handle.get_thrust_policy(), + { + rmm::device_uvector unique_type_end_offsets(nr_unique_types, handle.get_stream()); + thrust::copy_if(handle.get_thrust_policy(), + edge_types.begin(), + edge_types.end(), + thrust::make_counting_iterator(size_t{0}), + unique_types.begin(), + detail::is_first_in_run_t{edge_types.data()}); + + thrust::upper_bound(handle.get_thrust_policy(), edge_types.begin(), edge_types.end(), - thrust::make_constant_iterator(size_t{1}), unique_types.begin(), - unique_type_counts.begin()); + unique_types.end(), + unique_type_end_offsets.begin()); + + thrust::adjacent_difference(handle.get_thrust_policy(), + unique_type_end_offsets.begin(), + unique_type_end_offsets.end(), + unique_type_counts.begin()); + } } std::vector h_unique_types(unique_types.size()); @@ -634,20 +665,21 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku rmm::device_uvector type_offsets(nr_uniqe_edge_types_partition + 1, handle.get_stream()); - thrust::fill(handle.get_thrust_policy(), type_offsets.begin(), type_offsets.end(), edge_t{0}); + thrust::copy_if(handle.get_thrust_policy(), + edgelist_types.begin(), + edgelist_types.end(), + thrust::make_counting_iterator(size_t{0}), + unique_types.begin(), + detail::is_first_in_run_t{edgelist_types.data()}); - thrust::reduce_by_key(handle.get_thrust_policy(), - edgelist_types.begin(), - edgelist_types.end(), - thrust::make_constant_iterator(size_t{1}), - unique_types.begin(), - type_offsets.begin()); + type_offsets.set_element_to_zero_async(0, handle.get_stream()); - thrust::exclusive_scan(handle.get_thrust_policy(), - type_offsets.begin(), - type_offsets.end(), - type_offsets.begin(), - size_t{0}); + thrust::upper_bound(handle.get_thrust_policy(), + edgelist_types.begin(), + edgelist_types.end(), + unique_types.begin(), + unique_types.end(), + type_offsets.begin() + 1); std::vector h_unique_types(unique_types.size()); std::vector h_type_offsets(type_offsets.size()); @@ -714,7 +746,7 @@ lookup_endpoints_from_edge_ids_and_single_type( std::is_same_v, "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); - auto value_buffer = search_container.src_dst_from_edge_id_and_type( + auto value_buffer = search_container.lookup_from_edge_ids_and_single_type( handle, edge_ids_to_lookup, edge_type_to_lookup, multi_gpu); return std::make_tuple(std::move(std::get<0>(value_buffer)), @@ -747,7 +779,7 @@ lookup_endpoints_from_edge_ids_and_types( std::is_same_v, "edge_type_t must match EdgeTypeAndIdToSrcDstLookupContainerType::edge_type_type "); - auto value_buffer = search_container.src_dst_from_edge_id_and_type( + auto value_buffer = search_container.lookup_from_edge_ids_and_types( handle, edge_ids_to_lookup, edge_types_to_lookup, multi_gpu); return std::make_tuple(std::move(std::get<0>(value_buffer)), diff --git a/cpp/tests/lookup/lookup_src_dst_test.cpp b/cpp/tests/lookup/lookup_src_dst_test.cpp index c31ae533218..b2e4355dff4 100644 --- a/cpp/tests/lookup/lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/lookup_src_dst_test.cpp @@ -100,8 +100,9 @@ class Tests_SGLookupEdgeSrcDst // file once the graph generator is updated to generate edge ids and types. // - int32_t number_of_edge_types = - 1 + (std::rand() % (1 + (sg_graph_view.number_of_vertices() / (1 << 10)))); + int32_t number_of_edge_types = std::max( + 1 << 8, + static_cast(std::rand() % (1 + (sg_graph_view.number_of_vertices() / (1 << 16))))); std::optional> edge_types{ std::nullopt}; @@ -209,7 +210,7 @@ class Tests_SGLookupEdgeSrcDst if (id_or_type) (*h_mg_edge_ids)[random_idx] = std::numeric_limits::max(); else - (*h_mg_edge_types)[random_idx] = number_of_edge_types; + (*h_mg_edge_types)[random_idx] = std::numeric_limits::max() - 2; h_srcs_expected[random_idx] = cugraph::invalid_vertex_id::value; h_dsts_expected[random_idx] = cugraph::invalid_vertex_id::value; diff --git a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp index 22a5252be74..26119801b76 100644 --- a/cpp/tests/lookup/mg_lookup_src_dst_test.cpp +++ b/cpp/tests/lookup/mg_lookup_src_dst_test.cpp @@ -108,8 +108,9 @@ class Tests_MGLookupEdgeSrcDst // file once the graph generator is updated to generate edge ids and types. // - int32_t number_of_edge_types = - 1 + (std::rand() % (1 + (mg_graph_view.number_of_vertices() / (1 << 10)))); + int number_of_edge_types = std::max( + 1 << 8, + static_cast(std::rand() % (1 + (mg_graph_view.number_of_vertices() / (1 << 20))))); std::optional> edge_types{ std::nullopt}; @@ -246,7 +247,7 @@ class Tests_MGLookupEdgeSrcDst if (id_or_type) (*h_mg_edge_ids)[random_idx] = std::numeric_limits::max(); else - (*h_mg_edge_types)[random_idx] = number_of_edge_types; + (*h_mg_edge_types)[random_idx] = std::numeric_limits::max() - 2; h_srcs_expected[random_idx] = cugraph::invalid_vertex_id::value; h_dsts_expected[random_idx] = cugraph::invalid_vertex_id::value; From a95e7721cd49108d6af3f8e2a1993fd47ae75096 Mon Sep 17 00:00:00 2001 From: Naim Date: Thu, 6 Jun 2024 19:49:20 +0200 Subject: [PATCH 19/26] Rename compute_gpu_id_from_ext_edge_t to compute_gpu_id_from_ext_edge_id_t --- cpp/src/detail/graph_partition_utils.cuh | 2 +- cpp/src/lookup/lookup_src_dst_impl.cuh | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/src/detail/graph_partition_utils.cuh b/cpp/src/detail/graph_partition_utils.cuh index 8b10181e529..00931780266 100644 --- a/cpp/src/detail/graph_partition_utils.cuh +++ b/cpp/src/detail/graph_partition_utils.cuh @@ -51,7 +51,7 @@ struct compute_gpu_id_from_ext_vertex_t { }; template -struct compute_gpu_id_from_ext_edge_t { +struct compute_gpu_id_from_ext_edge_id_t { int comm_size{0}; int major_comm_size{0}; int minor_comm_size{0}; diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index 8b04da92ef2..ba83bdbcf77 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -114,13 +114,13 @@ struct lookup_container_t::lookup_con auto& minor_comm = handle.get_subcomm(cugraph::partition_manager::minor_comm_name()); auto const minor_comm_size = minor_comm.get_size(); - value_buffer = - cugraph::collect_values_for_keys(handle, - kv_store_object->view(), - edge_ids_to_lookup.begin(), - edge_ids_to_lookup.end(), - cugraph::detail::compute_gpu_id_from_ext_edge_t{ - comm_size, major_comm_size, minor_comm_size}); + value_buffer = cugraph::collect_values_for_keys( + handle, + kv_store_object->view(), + edge_ids_to_lookup.begin(), + edge_ids_to_lookup.end(), + cugraph::detail::compute_gpu_id_from_ext_edge_id_t{ + comm_size, major_comm_size, minor_comm_size}); } else { cugraph::resize_dataframe_buffer( value_buffer, edge_ids_to_lookup.size(), handle.get_stream()); @@ -403,7 +403,7 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku view_concat(edge_id_view, edge_type_view), cuda::proclaim_return_type>>( [key_func = - cugraph::detail::compute_gpu_id_from_ext_edge_t{ + cugraph::detail::compute_gpu_id_from_ext_edge_id_t{ comm_size, major_comm_size, minor_comm_size}] __device__(auto, @@ -637,7 +637,7 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku edgelist_ids.end(), edgelist_types.end())), [key_func = - cugraph::detail::compute_gpu_id_from_ext_edge_t{ + cugraph::detail::compute_gpu_id_from_ext_edge_id_t{ comm_size, major_comm_size, minor_comm_size}] __device__(auto val) { return key_func(thrust::get<2>(val)); }, From b9745fe50ccb2a411ad388f39a5e37cd43b722ba Mon Sep 17 00:00:00 2001 From: Naim Date: Thu, 6 Jun 2024 23:35:20 +0200 Subject: [PATCH 20/26] Use compute_number_of_edges_with_mask instead of count_set_bits --- cpp/src/lookup/lookup_src_dst_impl.cuh | 30 +++++++++++++++----------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index ba83bdbcf77..4182cb5f65e 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -573,14 +573,23 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku // decompress one edge_partition at a time // - auto number_of_local_edges = - graph_view.local_edge_partition_view(local_ep_idx).number_of_edges(); + auto edge_partition = edge_partition_device_view_t( + graph_view.local_edge_partition_view(local_ep_idx)); + auto edge_partition_mask_view = + graph_view.has_edge_mask() + ? std::make_optional< + detail::edge_partition_edge_property_device_view_t>( + *(graph_view.edge_mask_view()), local_ep_idx) + : std::nullopt; + + auto number_of_local_edges = edge_partition.number_of_edges(); if (graph_view.has_edge_mask()) { - number_of_local_edges = - detail::count_set_bits(handle, - (*(graph_view.edge_mask_view())).value_firsts()[local_ep_idx], - number_of_local_edges); + number_of_local_edges = edge_partition.compute_number_of_edges_with_mask( + (*edge_partition_mask_view).value_first(), + thrust::make_counting_iterator(edge_partition.major_range_first()), + thrust::make_counting_iterator(edge_partition.major_range_last()), + handle.get_stream()); } rmm::device_uvector edgelist_majors(number_of_local_edges, handle.get_stream()); @@ -591,19 +600,14 @@ EdgeTypeAndIdToSrcDstLookupContainerType build_edge_id_and_type_to_src_dst_looku detail::decompress_edge_partition_to_edgelist( handle, - edge_partition_device_view_t( - graph_view.local_edge_partition_view(local_ep_idx)), + edge_partition, std::nullopt, std::make_optional>( edge_id_view, local_ep_idx), std::make_optional< detail::edge_partition_edge_property_device_view_t>( edge_type_view, local_ep_idx), - graph_view.has_edge_mask() - ? std::make_optional< - detail::edge_partition_edge_property_device_view_t>( - *(graph_view.edge_mask_view()), local_ep_idx) - : std::nullopt, + edge_partition_mask_view, raft::device_span(edgelist_majors.data(), number_of_local_edges), raft::device_span(edgelist_minors.data(), number_of_local_edges), std::nullopt, From 7b6211076527a0696e055f03bbccaae20cfc881b Mon Sep 17 00:00:00 2001 From: Naim Date: Thu, 20 Jun 2024 01:54:56 +0200 Subject: [PATCH 21/26] c_api and plc binding for lookup src dst using edge ids and type(s) --- cpp/CMakeLists.txt | 1 + .../cugraph/src_dst_lookup_container.hpp | 4 +- cpp/include/cugraph_c/lookup_src_dst.h | 60 ++++ cpp/src/c_api/lookup_src_dst.cpp | 296 ++++++++++++++++++ cpp/src/c_api/lookup_src_dst.hpp | 45 +++ cpp/src/lookup/lookup_src_dst_impl.cuh | 11 +- .../_cugraph_c/lookup_src_dst.pxd | 64 ++++ 7 files changed, 478 insertions(+), 3 deletions(-) create mode 100644 cpp/include/cugraph_c/lookup_src_dst.h create mode 100644 cpp/src/c_api/lookup_src_dst.cpp create mode 100644 cpp/src/c_api/lookup_src_dst.hpp create mode 100644 python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 512729ff5c0..1388881282d 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -413,6 +413,7 @@ add_library(cugraph_c src/c_api/random.cpp src/c_api/similarity.cpp src/c_api/leiden.cpp + src/c_api/lookup_src_dst.cpp src/c_api/louvain.cpp src/c_api/triangle_count.cpp src/c_api/uniform_neighbor_sampling.cpp diff --git a/cpp/include/cugraph/src_dst_lookup_container.hpp b/cpp/include/cugraph/src_dst_lookup_container.hpp index 4b1509f0367..49e22c512cb 100644 --- a/cpp/include/cugraph/src_dst_lookup_container.hpp +++ b/cpp/include/cugraph/src_dst_lookup_container.hpp @@ -54,8 +54,8 @@ class lookup_container_t { lookup_container_t(raft::handle_t const& handle, std::vector types, std::vector type_counts); - lookup_container_t(const lookup_container_t&); - + lookup_container_t(lookup_container_t&& other); + lookup_container_t& operator=(lookup_container_t&& other); void insert(raft::handle_t const& handle, edge_type_t typ, raft::device_span edge_ids_to_insert, diff --git a/cpp/include/cugraph_c/lookup_src_dst.h b/cpp/include/cugraph_c/lookup_src_dst.h new file mode 100644 index 00000000000..72bad3c7d6e --- /dev/null +++ b/cpp/include/cugraph_c/lookup_src_dst.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 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. + * 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 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int32_t align_; +} lookup_container_t; + +typedef struct { + int32_t align_; +} lookup_result_t; + +cugraph_error_code_t cugraph_build_edge_id_and_type_to_src_dst_lookup_map( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + lookup_container_t** lookup_container, + cugraph_error_t** error); + +cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_single_type( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + const lookup_container_t* lookup_container, + const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, + int edge_type_to_lookup, + lookup_result_t** result, + cugraph_error_t** error); + +cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + const lookup_container_t* lookup_container, + const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, + const cugraph_type_erased_device_array_view_t* edge_types_to_lookup, + lookup_result_t** result, + cugraph_error_t** error); + +#ifdef __cplusplus +} +#endif diff --git a/cpp/src/c_api/lookup_src_dst.cpp b/cpp/src/c_api/lookup_src_dst.cpp new file mode 100644 index 00000000000..564d3fb2bf4 --- /dev/null +++ b/cpp/src/c_api/lookup_src_dst.cpp @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2023-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. + * 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. + */ + +#include "c_api/lookup_src_dst.hpp" + +#include "c_api/abstract_functor.hpp" +#include "c_api/graph.hpp" +#include "c_api/graph_helper.hpp" +#include "c_api/hierarchical_clustering_result.hpp" +#include "c_api/random.hpp" +#include "c_api/resource_handle.hpp" +#include "c_api/utils.hpp" + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +namespace { + +struct build_lookup_map_functor : public cugraph::c_api::abstract_functor { + raft::handle_t const& handle_; + cugraph::c_api::cugraph_graph_t* graph_{nullptr}; + cugraph::c_api::lookup_container_t* result_{}; + + build_lookup_map_functor(::cugraph_resource_handle_t const* handle, ::cugraph_graph_t* graph) + : abstract_functor(), + handle_(*reinterpret_cast(handle)->handle_), + graph_(reinterpret_cast(graph)) + { + } + + template + void operator()() + { + if constexpr (!cugraph::is_candidate::value) { + unsupported(); + } else { + // ecg expects store_transposed == false + if constexpr (store_transposed) { + error_code_ = cugraph::c_api:: + transpose_storage( + handle_, graph_, error_.get()); + if (error_code_ != CUGRAPH_SUCCESS) return; + } + + auto graph = + reinterpret_cast*>(graph_->graph_); + + auto graph_view = graph->view(); + + auto edge_ids = reinterpret_cast< + cugraph::edge_property_t, + edge_t>*>(graph_->edge_type_); + auto edge_types = reinterpret_cast< + cugraph::edge_property_t, + edge_type_type_t>*>(graph_->edge_type_id_type_); + + auto number_map = reinterpret_cast*>(graph_->number_map_); + + rmm::device_uvector clusters(0, handle_.get_stream()); + + auto lookup_container = new cugraph::lookup_container_t(); + + cugraph::build_edge_id_and_type_to_src_dst_lookup_map( + handle_, graph_view, edge_ids->view(), edge_types->view()); + + *lookup_container = std::move(cugraph::build_edge_id_and_type_to_src_dst_lookup_map( + handle_, graph_view, edge_ids->view(), edge_types->view())); + + auto result = new cugraph::c_api::lookup_container_t{ + graph_->edge_type_, graph_->edge_type_id_type_, graph_->vertex_type_, lookup_container}; + + result_ = reinterpret_cast(result); + } + } +}; + +struct lookup_using_edge_ids_of_single_type_functor : public cugraph::c_api::abstract_functor { + raft::handle_t const& handle_; + cugraph::c_api::cugraph_graph_t* graph_{nullptr}; + cugraph::c_api::lookup_container_t const* lookup_container_{nullptr}; + cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_ids_to_lookup_{nullptr}; + int edge_type_to_lookup_{}; + cugraph::c_api::lookup_result_t* result_{nullptr}; + + lookup_using_edge_ids_of_single_type_functor( + cugraph_resource_handle_t const* handle, + cugraph_graph_t* graph, + lookup_container_t const* lookup_container, + cugraph_type_erased_device_array_view_t const* edge_ids_to_lookup, + int edge_type_to_lookup) + : abstract_functor(), + handle_(*reinterpret_cast(handle)->handle_), + graph_(reinterpret_cast(graph)), + lookup_container_( + reinterpret_cast(lookup_container)), + edge_ids_to_lookup_( + reinterpret_cast( + edge_ids_to_lookup)), + edge_type_to_lookup_(edge_type_to_lookup) + { + } + + template + void operator()() + { + if constexpr (!cugraph::is_candidate::value) { + unsupported(); + } else { + // ecg expects store_transposed == false + if constexpr (store_transposed) { + error_code_ = cugraph::c_api:: + transpose_storage( + handle_, graph_, error_.get()); + if (error_code_ != CUGRAPH_SUCCESS) return; + } + + auto graph = + reinterpret_cast*>(graph_->graph_); + + auto graph_view = graph->view(); + + assert(edge_ids_to_lookup_); + + auto result = cugraph::lookup_endpoints_from_edge_ids_and_single_type( + handle_, + *(reinterpret_cast*>( + lookup_container_->lookup_container_)), + raft::device_span(edge_ids_to_lookup_->as_type(), + edge_ids_to_lookup_->size_), + edge_type_to_lookup_); + + auto number_map = reinterpret_cast*>(graph_->number_map_); + + result_ = new cugraph::c_api::lookup_result_t{ + new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<0>(result), + lookup_container_->vertex_type_), + new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<1>(result), + lookup_container_->vertex_type_)}; + } + } +}; + +struct lookup_using_edge_ids_and_types_functor : public cugraph::c_api::abstract_functor { + raft::handle_t const& handle_; + cugraph::c_api::cugraph_graph_t* graph_{nullptr}; + cugraph::c_api::lookup_container_t const* lookup_container_{nullptr}; + cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_ids_to_lookup_{nullptr}; + cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_types_to_lookup_{nullptr}; + cugraph::c_api::lookup_result_t* result_{nullptr}; + + lookup_using_edge_ids_and_types_functor( + cugraph_resource_handle_t const* handle, + cugraph_graph_t* graph, + lookup_container_t const* lookup_container, + cugraph_type_erased_device_array_view_t const* edge_ids_to_lookup, + cugraph_type_erased_device_array_view_t const* edge_types_to_lookup) + : abstract_functor(), + handle_(*reinterpret_cast(handle)->handle_), + graph_(reinterpret_cast(graph)), + lookup_container_( + reinterpret_cast(lookup_container)), + edge_ids_to_lookup_( + reinterpret_cast( + edge_ids_to_lookup)), + edge_types_to_lookup_( + reinterpret_cast( + edge_types_to_lookup)) + { + } + + template + void operator()() + { + if constexpr (!cugraph::is_candidate::value) { + unsupported(); + } else { + // ecg expects store_transposed == false + if constexpr (store_transposed) { + error_code_ = cugraph::c_api:: + transpose_storage( + handle_, graph_, error_.get()); + if (error_code_ != CUGRAPH_SUCCESS) return; + } + + auto graph = + reinterpret_cast*>(graph_->graph_); + + auto graph_view = graph->view(); + + assert(edge_ids_to_lookup_); + assert(edge_types_to_lookup_); + + auto result = cugraph:: + lookup_endpoints_from_edge_ids_and_types( + handle_, + *(reinterpret_cast*>( + lookup_container_->lookup_container_)), + raft::device_span(edge_ids_to_lookup_->as_type(), + edge_ids_to_lookup_->size_), + raft::device_span( + edge_types_to_lookup_->as_type(), edge_types_to_lookup_->size_)); + + auto number_map = reinterpret_cast*>(graph_->number_map_); + + result_ = new cugraph::c_api::lookup_result_t{ + new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<0>(result), + lookup_container_->vertex_type_), + new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<1>(result), + lookup_container_->vertex_type_)}; + } + } +}; + +} // namespace + +extern "C" cugraph_error_code_t cugraph_build_edge_id_and_type_to_src_dst_lookup_map( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + lookup_container_t** lookup_container, + cugraph_error_t** error) +{ + build_lookup_map_functor functor(handle, graph); + + return cugraph::c_api::run_algorithm(graph, functor, lookup_container, error); +} + +extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + const lookup_container_t* lookup_container, + const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, + const cugraph_type_erased_device_array_view_t* edge_types_to_lookup, + lookup_result_t** result, + cugraph_error_t** error) +{ + lookup_using_edge_ids_and_types_functor functor( + handle, graph, lookup_container, edge_ids_to_lookup, edge_types_to_lookup); + + return cugraph::c_api::run_algorithm(graph, functor, result, error); +} + +extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_single_type( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + const lookup_container_t* lookup_container, + const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, + int edge_type_to_lookup, + lookup_result_t** result, + cugraph_error_t** error) +{ + lookup_using_edge_ids_of_single_type_functor functor( + handle, graph, lookup_container, edge_ids_to_lookup, edge_type_to_lookup); + + return cugraph::c_api::run_algorithm(graph, functor, result, error); +} diff --git a/cpp/src/c_api/lookup_src_dst.hpp b/cpp/src/c_api/lookup_src_dst.hpp new file mode 100644 index 00000000000..41218ae6080 --- /dev/null +++ b/cpp/src/c_api/lookup_src_dst.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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. + * 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 "c_api/array.hpp" +#include "c_api/error.hpp" + +#include + +#include +#include + +#include + +namespace cugraph { +namespace c_api { + +struct lookup_container_t { + cugraph_data_type_id_t edge_type_; + cugraph_data_type_id_t edge_type_id_type_; + cugraph_data_type_id_t vertex_type_; + + void* lookup_container_; +}; + +struct lookup_result_t { + cugraph_type_erased_device_array_t* srcs_{nullptr}; + cugraph_type_erased_device_array_t* dsts_{nullptr}; +}; + +} // namespace c_api +} // namespace cugraph diff --git a/cpp/src/lookup/lookup_src_dst_impl.cuh b/cpp/src/lookup/lookup_src_dst_impl.cuh index 4182cb5f65e..1c8c39fd6dd 100644 --- a/cpp/src/lookup/lookup_src_dst_impl.cuh +++ b/cpp/src/lookup/lookup_src_dst_impl.cuh @@ -310,10 +310,19 @@ lookup_container_t::lookup_container_ template lookup_container_t::lookup_container_t( - const lookup_container_t&) + lookup_container_t&& other) + : pimpl{std::move(other.pimpl)} { } +template +lookup_container_t& +lookup_container_t::operator=(lookup_container_t&& other) +{ + pimpl = std::move(other.pimpl); + return *this; +} + template void lookup_container_t::insert( raft::handle_t const& handle, diff --git a/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd b/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd new file mode 100644 index 00000000000..6bf6085eb5d --- /dev/null +++ b/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd @@ -0,0 +1,64 @@ +# Copyright (c) 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. +# 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. + +# Have cython use python 3 syntax +# cython: language_level = 3 + + +from pylibcugraph._cugraph_c.resource_handle cimport ( + bool_t, + cugraph_resource_handle_t, +) +from pylibcugraph._cugraph_c.error cimport ( + cugraph_error_code_t, + cugraph_error_t, +) +from pylibcugraph._cugraph_c.array cimport ( + cugraph_type_erased_device_array_view_t, +) +from pylibcugraph._cugraph_c.graph cimport ( + cugraph_graph_t, +) + +cdef extern from "cugraph_c/lookup_src_dst.h": + ########################################################################### + + ctypedef struct lookup_container_t: + pass + + ctypedef struct lookup_result_t: + pass + + cdef cugraph_error_code_t cugraph_build_edge_id_and_type_to_src_dst_lookup_map( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + lookup_container_t** lookup_container, + cugraph_error_t** error) + + cdef cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_single_type( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + const lookup_container_t* lookup_container, + const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, + int edge_type_to_lookup, + lookup_container_t** result, + cugraph_error_t** error) + + cdef cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + const lookup_container_t* lookup_container, + const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, + const cugraph_type_erased_device_array_view_t* edge_types_to_lookup, + lookup_container_t** result, + cugraph_error_t** error) From 39a3332198833982d10d5f4f6ef649c792b99f00 Mon Sep 17 00:00:00 2001 From: Naim Date: Mon, 24 Jun 2024 16:55:49 +0200 Subject: [PATCH 22/26] Fix return type --- .../pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd b/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd index 6bf6085eb5d..7348b35fc98 100644 --- a/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd +++ b/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd @@ -51,7 +51,7 @@ cdef extern from "cugraph_c/lookup_src_dst.h": const lookup_container_t* lookup_container, const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, int edge_type_to_lookup, - lookup_container_t** result, + lookup_result_t** result, cugraph_error_t** error) cdef cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types( @@ -60,5 +60,5 @@ cdef extern from "cugraph_c/lookup_src_dst.h": const lookup_container_t* lookup_container, const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, const cugraph_type_erased_device_array_view_t* edge_types_to_lookup, - lookup_container_t** result, + lookup_result_t** result, cugraph_error_t** error) From 3858807692e6ba030881e8af90718a4b41643401 Mon Sep 17 00:00:00 2001 From: Naim Date: Tue, 25 Jun 2024 01:25:20 +0200 Subject: [PATCH 23/26] Add MG CAPI test --- cpp/include/cugraph_c/algorithms.h | 4 +- cpp/include/cugraph_c/lookup_src_dst.h | 95 +++++++- cpp/include/cugraph_c/sampling_algorithms.h | 10 +- cpp/src/c_api/lookup_src_dst.cpp | 84 ++++--- cpp/src/c_api/lookup_src_dst.hpp | 6 +- cpp/tests/CMakeLists.txt | 1 + cpp/tests/c_api/mg_lookup_src_dst_test.c | 224 ++++++++++++++++++ .../_cugraph_c/lookup_src_dst.pxd | 20 +- 8 files changed, 392 insertions(+), 52 deletions(-) create mode 100644 cpp/tests/c_api/mg_lookup_src_dst_test.c diff --git a/cpp/include/cugraph_c/algorithms.h b/cpp/include/cugraph_c/algorithms.h index 1ccbc7bf868..ea8629a8217 100644 --- a/cpp/include/cugraph_c/algorithms.h +++ b/cpp/include/cugraph_c/algorithms.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, NVIDIA CORPORATION. + * Copyright (c) 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. @@ -28,10 +28,10 @@ #include #include #include +#include #include #include #include - /** * @} */ diff --git a/cpp/include/cugraph_c/lookup_src_dst.h b/cpp/include/cugraph_c/lookup_src_dst.h index 72bad3c7d6e..f4d63572e82 100644 --- a/cpp/include/cugraph_c/lookup_src_dst.h +++ b/cpp/include/cugraph_c/lookup_src_dst.h @@ -18,43 +18,124 @@ #include #include +#include #ifdef __cplusplus extern "C" { #endif +/** + * @brief Opaque src-dst lookup container type + */ + typedef struct { int32_t align_; -} lookup_container_t; +} cugraph_lookup_container_t; + +/** + * @brief Opaque src-dst lookup result type + */ typedef struct { int32_t align_; -} lookup_result_t; +} cugraph_lookup_result_t; +/** + * @brief Build map to lookup source and destination using edge id and type + * + * @param [in] handle Handle for accessing resources + * @param [in] graph Pointer to graph. NOTE: Graph might be modified if the storage + * needs to be transposed + * @param [out] lookup_container Lookup map + * @param [out] error Pointer to an error object storing details of any error. Will + * be populated if error code is not CUGRAPH_SUCCESS + * @return error code + */ cugraph_error_code_t cugraph_build_edge_id_and_type_to_src_dst_lookup_map( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - lookup_container_t** lookup_container, + cugraph_lookup_container_t** lookup_container, cugraph_error_t** error); +/** + * @brief Lookup edge sources and destinations using edge ids and a single edge type. + * + * Use this function to lookup endpoints of edges belonging to the same edge type. + * + * @param [in] handle Handle for accessing resources + * @param [in] graph Pointer to graph. NOTE: Graph might be modified if the storage + * needs to be transposed + * @param [in] lookup_container Lookup map + * @param[in] edge_ids_to_lookup Edge ids to lookup + * @param[in] edge_type_to_lookup Edge types corresponding to edge ids in @p edge_ids_to_lookup + * @param [out] result Output from the lookup call + * @param [out] error Pointer to an error object storing details of any error. Will + * be populated if error code is not CUGRAPH_SUCCESS + * @return error code + */ cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_single_type( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - const lookup_container_t* lookup_container, + const cugraph_lookup_container_t* lookup_container, const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, int edge_type_to_lookup, - lookup_result_t** result, + cugraph_lookup_result_t** result, cugraph_error_t** error); +/** + * @brief Lookup edge sources and destinations using edge ids and edge types. + * + * Use this function to lookup endpoints of edges belonging to different edge types. + * + * @param [in] handle Handle for accessing resources + * @param [in] graph Pointer to graph. NOTE: Graph might be modified if the storage + * needs to be transposed + * @param [in] lookup_container Lookup map + * @param[in] edge_ids_to_lookup Edge ids to lookup + * @param[in] edge_types_to_lookup Edge types corresponding to the edge ids in @p + * edge_ids_to_lookup + * @param [out] result Output from the lookup call + * @param [out] error Pointer to an error object storing details of any error. Will + * be populated if error code is not CUGRAPH_SUCCESS + * @return error code + */ cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - const lookup_container_t* lookup_container, + const cugraph_lookup_container_t* lookup_container, const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, const cugraph_type_erased_device_array_view_t* edge_types_to_lookup, - lookup_result_t** result, + cugraph_lookup_result_t** result, cugraph_error_t** error); +/** + * @ingroup samplingC + * @brief Get the edge sources from the lookup result + * + * @param [in] result The result from src-dst lookup using edge ids and type(s) + * @return type erased array pointing to the edge sources + */ +cugraph_type_erased_device_array_view_t* cugraph_lookup_result_get_srcs( + const cugraph_lookup_result_t* result); + +/** + * @ingroup samplingC + * @brief Get the edge destinations from the lookup result + * + * @param [in] result The result from src-dst lookup using edge ids and type(s) + * @return type erased array pointing to the edge destinations + */ +cugraph_type_erased_device_array_view_t* cugraph_lookup_result_get_dsts( + const cugraph_lookup_result_t* result); + +/** + * @ingroup samplingC + * @brief Free a src-dst lookup result + * + * @param [in] result The result from src-dst lookup using edge ids and type(s) + */ +void cugraph_lookup_result_free(cugraph_lookup_result_t* result); + #ifdef __cplusplus } #endif diff --git a/cpp/include/cugraph_c/sampling_algorithms.h b/cpp/include/cugraph_c/sampling_algorithms.h index 35f60e195be..a7490ad2c63 100644 --- a/cpp/include/cugraph_c/sampling_algorithms.h +++ b/cpp/include/cugraph_c/sampling_algorithms.h @@ -43,7 +43,7 @@ typedef struct { * needs to be transposed * @param [in] start_vertices Array of source vertices * @param [in] max_length Maximum length of the generated path - * @param [in] result Output from the node2vec call + * @param [out] result Output from the node2vec call * @param [out] error Pointer to an error object storing details of any error. Will * be populated if error code is not CUGRAPH_SUCCESS * @return error code @@ -64,7 +64,7 @@ cugraph_error_code_t cugraph_uniform_random_walks( * needs to be transposed * @param [in] start_vertices Array of source vertices * @param [in] max_length Maximum length of the generated path - * @param [in] result Output from the node2vec call + * @param [out] result Output from the node2vec call * @param [out] error Pointer to an error object storing details of any error. Will * be populated if error code is not CUGRAPH_SUCCESS * @return error code @@ -89,7 +89,7 @@ cugraph_error_code_t cugraph_biased_random_walks( * otherwise return as a dense matrix * @param [in] p The return parameter * @param [in] q The in/out parameter - * @param [in] result Output from the node2vec call + * @param [out] result Output from the node2vec call * @param [out] error Pointer to an error object storing details of any error. Will * be populated if error code is not CUGRAPH_SUCCESS * @return error code @@ -117,7 +117,7 @@ cugraph_error_code_t cugraph_node2vec_random_walks( * otherwise return as a dense matrix * @param [in] p The return parameter * @param [in] q The in/out parameter - * @param [in] result Output from the node2vec call + * @param [out] result Output from the node2vec call * @param [out] error Pointer to an error object storing details of any error. Will * be populated if error code is not CUGRAPH_SUCCESS * @return error code @@ -353,7 +353,7 @@ void cugraph_sampling_options_free(cugraph_sampling_options_t* options); * Opaque pointer defining the sampling options. * @param [in] do_expensive_check * A flag to run expensive checks for input arguments (if set to true) - * @param [in] result Output from the uniform_neighbor_sample call + * @param [out] result Output from the uniform_neighbor_sample call * @param [out] error Pointer to an error object storing details of any error. Will * be populated if error code is not CUGRAPH_SUCCESS * @return error code diff --git a/cpp/src/c_api/lookup_src_dst.cpp b/cpp/src/c_api/lookup_src_dst.cpp index 564d3fb2bf4..25a9fb78ebc 100644 --- a/cpp/src/c_api/lookup_src_dst.cpp +++ b/cpp/src/c_api/lookup_src_dst.cpp @@ -19,13 +19,12 @@ #include "c_api/abstract_functor.hpp" #include "c_api/graph.hpp" #include "c_api/graph_helper.hpp" -#include "c_api/hierarchical_clustering_result.hpp" -#include "c_api/random.hpp" #include "c_api/resource_handle.hpp" #include "c_api/utils.hpp" -#include -#include +// #include +// #include +#include #include #include @@ -42,7 +41,7 @@ namespace { struct build_lookup_map_functor : public cugraph::c_api::abstract_functor { raft::handle_t const& handle_; cugraph::c_api::cugraph_graph_t* graph_{nullptr}; - cugraph::c_api::lookup_container_t* result_{}; + cugraph::c_api::cugraph_lookup_container_t* result_{}; build_lookup_map_functor(::cugraph_resource_handle_t const* handle, ::cugraph_graph_t* graph) : abstract_functor(), @@ -84,20 +83,23 @@ struct build_lookup_map_functor : public cugraph::c_api::abstract_functor { auto number_map = reinterpret_cast*>(graph_->number_map_); - rmm::device_uvector clusters(0, handle_.get_stream()); - auto lookup_container = new cugraph::lookup_container_t(); + std::cout << "\n\nGoing to call cugraph::build_edge_id_and_type_to_src_dst_lookup_map\n\n"; + cugraph::build_edge_id_and_type_to_src_dst_lookup_map( handle_, graph_view, edge_ids->view(), edge_types->view()); - *lookup_container = std::move(cugraph::build_edge_id_and_type_to_src_dst_lookup_map( - handle_, graph_view, edge_ids->view(), edge_types->view())); + std::cout << "\n\nAfter calling cugraph::build_edge_id_and_type_to_src_dst_lookup_map\n\n"; + /* + *lookup_container = std::move(cugraph::build_edge_id_and_type_to_src_dst_lookup_map( + handle_, graph_view, edge_ids->view(), edge_types->view())); - auto result = new cugraph::c_api::lookup_container_t{ - graph_->edge_type_, graph_->edge_type_id_type_, graph_->vertex_type_, lookup_container}; + auto result = new cugraph::c_api::cugraph_lookup_container_t{ + graph_->edge_type_, graph_->edge_type_id_type_, graph_->vertex_type_, lookup_container}; - result_ = reinterpret_cast(result); + result_ = reinterpret_cast(result); + */ } } }; @@ -105,22 +107,22 @@ struct build_lookup_map_functor : public cugraph::c_api::abstract_functor { struct lookup_using_edge_ids_of_single_type_functor : public cugraph::c_api::abstract_functor { raft::handle_t const& handle_; cugraph::c_api::cugraph_graph_t* graph_{nullptr}; - cugraph::c_api::lookup_container_t const* lookup_container_{nullptr}; + cugraph::c_api::cugraph_lookup_container_t const* lookup_container_{nullptr}; cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_ids_to_lookup_{nullptr}; int edge_type_to_lookup_{}; - cugraph::c_api::lookup_result_t* result_{nullptr}; + cugraph::c_api::cugraph_lookup_result_t* result_{nullptr}; lookup_using_edge_ids_of_single_type_functor( cugraph_resource_handle_t const* handle, cugraph_graph_t* graph, - lookup_container_t const* lookup_container, + cugraph_lookup_container_t const* lookup_container, cugraph_type_erased_device_array_view_t const* edge_ids_to_lookup, int edge_type_to_lookup) : abstract_functor(), handle_(*reinterpret_cast(handle)->handle_), graph_(reinterpret_cast(graph)), lookup_container_( - reinterpret_cast(lookup_container)), + reinterpret_cast(lookup_container)), edge_ids_to_lookup_( reinterpret_cast( edge_ids_to_lookup)), @@ -167,7 +169,7 @@ struct lookup_using_edge_ids_of_single_type_functor : public cugraph::c_api::abs auto number_map = reinterpret_cast*>(graph_->number_map_); - result_ = new cugraph::c_api::lookup_result_t{ + result_ = new cugraph::c_api::cugraph_lookup_result_t{ new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<0>(result), lookup_container_->vertex_type_), new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<1>(result), @@ -179,22 +181,22 @@ struct lookup_using_edge_ids_of_single_type_functor : public cugraph::c_api::abs struct lookup_using_edge_ids_and_types_functor : public cugraph::c_api::abstract_functor { raft::handle_t const& handle_; cugraph::c_api::cugraph_graph_t* graph_{nullptr}; - cugraph::c_api::lookup_container_t const* lookup_container_{nullptr}; + cugraph::c_api::cugraph_lookup_container_t const* lookup_container_{nullptr}; cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_ids_to_lookup_{nullptr}; cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_types_to_lookup_{nullptr}; - cugraph::c_api::lookup_result_t* result_{nullptr}; + cugraph::c_api::cugraph_lookup_result_t* result_{nullptr}; lookup_using_edge_ids_and_types_functor( cugraph_resource_handle_t const* handle, cugraph_graph_t* graph, - lookup_container_t const* lookup_container, + cugraph_lookup_container_t const* lookup_container, cugraph_type_erased_device_array_view_t const* edge_ids_to_lookup, cugraph_type_erased_device_array_view_t const* edge_types_to_lookup) : abstract_functor(), handle_(*reinterpret_cast(handle)->handle_), graph_(reinterpret_cast(graph)), lookup_container_( - reinterpret_cast(lookup_container)), + reinterpret_cast(lookup_container)), edge_ids_to_lookup_( reinterpret_cast( edge_ids_to_lookup)), @@ -243,7 +245,7 @@ struct lookup_using_edge_ids_and_types_functor : public cugraph::c_api::abstract auto number_map = reinterpret_cast*>(graph_->number_map_); - result_ = new cugraph::c_api::lookup_result_t{ + result_ = new cugraph::c_api::cugraph_lookup_result_t{ new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<0>(result), lookup_container_->vertex_type_), new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<1>(result), @@ -257,21 +259,23 @@ struct lookup_using_edge_ids_and_types_functor : public cugraph::c_api::abstract extern "C" cugraph_error_code_t cugraph_build_edge_id_and_type_to_src_dst_lookup_map( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - lookup_container_t** lookup_container, + cugraph_lookup_container_t** lookup_container, cugraph_error_t** error) { + std::cout << "\nbefore functor\n"; build_lookup_map_functor functor(handle, graph); - + std::cout << "\nafter functor, bfore run algo\n"; return cugraph::c_api::run_algorithm(graph, functor, lookup_container, error); + std::cout << "\nafter run algo\n"; } extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - const lookup_container_t* lookup_container, + const cugraph_lookup_container_t* lookup_container, const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, const cugraph_type_erased_device_array_view_t* edge_types_to_lookup, - lookup_result_t** result, + cugraph_lookup_result_t** result, cugraph_error_t** error) { lookup_using_edge_ids_and_types_functor functor( @@ -283,10 +287,10 @@ extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_single_type( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - const lookup_container_t* lookup_container, + const cugraph_lookup_container_t* lookup_container, const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, int edge_type_to_lookup, - lookup_result_t** result, + cugraph_lookup_result_t** result, cugraph_error_t** error) { lookup_using_edge_ids_of_single_type_functor functor( @@ -294,3 +298,27 @@ extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_singl return cugraph::c_api::run_algorithm(graph, functor, result, error); } + +extern "C" cugraph_type_erased_device_array_view_t* cugraph_lookup_result_get_srcs( + const cugraph_lookup_result_t* result) +{ + auto internal_pointer = reinterpret_cast(result); + return reinterpret_cast( + internal_pointer->srcs_->view()); +} + +extern "C" cugraph_type_erased_device_array_view_t* cugraph_lookup_result_get_dsts( + const cugraph_lookup_result_t* result) +{ + auto internal_pointer = reinterpret_cast(result); + return reinterpret_cast( + internal_pointer->dsts_->view()); +} + +extern "C" void cugraph_lookup_result_free(cugraph_lookup_result_t* result) +{ + auto internal_pointer = reinterpret_cast(result); + delete internal_pointer->srcs_; + delete internal_pointer->dsts_; + delete internal_pointer; +} diff --git a/cpp/src/c_api/lookup_src_dst.hpp b/cpp/src/c_api/lookup_src_dst.hpp index 41218ae6080..bfd6213093b 100644 --- a/cpp/src/c_api/lookup_src_dst.hpp +++ b/cpp/src/c_api/lookup_src_dst.hpp @@ -18,7 +18,7 @@ #include "c_api/array.hpp" #include "c_api/error.hpp" -#include +// #include #include #include @@ -28,7 +28,7 @@ namespace cugraph { namespace c_api { -struct lookup_container_t { +struct cugraph_lookup_container_t { cugraph_data_type_id_t edge_type_; cugraph_data_type_id_t edge_type_id_type_; cugraph_data_type_id_t vertex_type_; @@ -36,7 +36,7 @@ struct lookup_container_t { void* lookup_container_; }; -struct lookup_result_t { +struct cugraph_lookup_result_t { cugraph_type_erased_device_array_t* srcs_{nullptr}; cugraph_type_erased_device_array_t* dsts_{nullptr}; }; diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index fd356ff8b89..0a64dffe804 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -763,6 +763,7 @@ if(BUILD_CUGRAPH_MG_TESTS) ConfigureCTestMG(MG_CAPI_EDGE_BETWEENNESS_CENTRALITY_TEST c_api/mg_edge_betweenness_centrality_test.c) ConfigureCTestMG(MG_CAPI_HITS_TEST c_api/mg_hits_test.c) ConfigureCTestMG(MG_CAPI_UNIFORM_NEIGHBOR_SAMPLE_TEST c_api/mg_uniform_neighbor_sample_test.c) + ConfigureCTestMG(MG_CAPI_LOOKUP_SRC_DST_TEST c_api/mg_lookup_src_dst_test.c) ConfigureCTestMG(MG_CAPI_RANDOM_WALKS_TEST c_api/mg_random_walks_test.c) ConfigureCTestMG(MG_CAPI_TRIANGLE_COUNT_TEST c_api/mg_triangle_count_test.c) ConfigureCTestMG(MG_CAPI_LOUVAIN_TEST c_api/mg_louvain_test.c) diff --git a/cpp/tests/c_api/mg_lookup_src_dst_test.c b/cpp/tests/c_api/mg_lookup_src_dst_test.c new file mode 100644 index 00000000000..83330e0b335 --- /dev/null +++ b/cpp/tests/c_api/mg_lookup_src_dst_test.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 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. + * 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. + */ + +#include "mg_test_utils.h" /* RUN_TEST */ + +#include +#include + +#include + +typedef int32_t vertex_t; +typedef int32_t edge_t; +typedef int32_t edge_type_t; + +typedef float weight_t; + +data_type_id_t vertex_tid = INT32; +data_type_id_t edge_tid = INT32; +data_type_id_t weight_tid = FLOAT32; +data_type_id_t edge_id_tid = INT32; +data_type_id_t edge_type_tid = INT32; + +int generic_lookup_src_dst_test(const cugraph_resource_handle_t* handle, + vertex_t* h_srcs, + vertex_t* h_dsts, + edge_t* h_edge_ids, + edge_type_t* h_edge_types, + size_t num_vertices, + size_t num_edges, + bool_t store_transposed, + edge_t* edge_ids_to_lookup, + edge_type_t* edge_types_to_lookup, + size_t num_edge_ids_to_lookup, + vertex_t* h_expected_srcs, + vertex_t* h_expected_dsts) +{ + int test_ret_value = 0; + + cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; + cugraph_error_t* ret_error; + + cugraph_graph_t* graph = NULL; + cugraph_lookup_container_t* lookup_container = NULL; + cugraph_lookup_result_t* result = NULL; + + int rank = cugraph_resource_handle_get_rank(handle); + + ret_code = create_mg_test_graph_new(handle, + vertex_tid, + edge_tid, + h_srcs, + h_dsts, + weight_tid, + NULL, + edge_type_tid, + h_edge_types, + edge_id_tid, + h_edge_ids, + num_edges, + FALSE, /*store_transposed*/ + TRUE, /*renumber*/ + TRUE, /*is_symmetric*/ + FALSE, /*is_multigraph*/ + &graph, + &ret_error); + + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_test_graph failed."); + TEST_ALWAYS_ASSERT(ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); + + ret_code = cugraph_build_edge_id_and_type_to_src_dst_lookup_map( + handle, graph, &lookup_container, &ret_error); + + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); + TEST_ALWAYS_ASSERT(ret_code == CUGRAPH_SUCCESS, "cugraph_ecg failed."); + +#if 0 + cugraph_type_erased_device_array_t* d_edge_ids_to_lookup = NULL; + cugraph_type_erased_device_array_view_t* d_edge_ids_to_lookup_view = NULL; + + ret_code = cugraph_type_erased_device_array_create( + handle, num_edge_ids_to_lookup, edge_id_tid, &d_edge_ids_to_lookup, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "d_edge_ids_to_lookup create failed."); + + d_edge_ids_to_lookup_view = cugraph_type_erased_device_array_view(d_edge_ids_to_lookup); + + ret_code = cugraph_type_erased_device_array_view_copy_from_host( + handle, d_edge_ids_to_lookup_view, (byte_t*)edge_ids_to_lookup, &ret_error); + + cugraph_type_erased_device_array_t* d_edge_types_to_lookup = NULL; + cugraph_type_erased_device_array_view_t* d_edge_types_to_lookup_view = NULL; + + ret_code = cugraph_type_erased_device_array_create( + handle, num_edge_ids_to_lookup, edge_type_tid, &d_edge_types_to_lookup, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "d_edge_types_to_lookup create failed."); + + d_edge_types_to_lookup_view = cugraph_type_erased_device_array_view(d_edge_types_to_lookup); + + ret_code = cugraph_type_erased_device_array_view_copy_from_host( + handle, d_edge_types_to_lookup_view, (byte_t*)edge_types_to_lookup, &ret_error); + + ret_code = cugraph_lookup_endpoints_from_edge_ids_and_types(handle, + graph, + lookup_container, + d_edge_ids_to_lookup_view, + d_edge_types_to_lookup_view, + &result, + &ret_error); + + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); + TEST_ALWAYS_ASSERT(ret_code == CUGRAPH_SUCCESS, "cugraph_ecg failed."); + + if (test_ret_value == 0) { + cugraph_type_erased_device_array_view_t* d_srcs; + cugraph_type_erased_device_array_view_t* d_dsts; + + d_srcs = cugraph_lookup_result_get_srcs(result); + d_dsts = cugraph_lookup_result_get_dsts(result); + + vertex_t h_result_srcs[num_edge_ids_to_lookup]; + edge_t h_result_dsts[num_edge_ids_to_lookup]; + + ret_code = cugraph_type_erased_device_array_view_copy_to_host( + handle, (byte_t*)h_result_srcs, d_srcs, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); + + ret_code = cugraph_type_erased_device_array_view_copy_to_host( + handle, (byte_t*)h_result_dsts, d_dsts, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); + + size_t result_num_edges = cugraph_type_erased_device_array_view_size(d_srcs); + + TEST_ALWAYS_ASSERT(result_num_edges == num_edge_ids_to_lookup, + "number of edges in returned result") + + for (int i = 0; i < num_edge_ids_to_lookup; i++) { + printf("\n %d %d\n", h_result_srcs[i], h_result_dsts[i]); + vertex_t src = (h_result_srcs[i] < h_result_dsts[i]) ? h_result_srcs[i] : h_result_dsts[i]; + vertex_t dst = (h_result_srcs[i] >= h_result_dsts[i]) ? h_result_srcs[i] : h_result_dsts[i]; + printf("\n%d %d\n", src, dst); + TEST_ASSERT(test_ret_value, + src == h_expected_srcs[i], + "expected sources don't match with returned ones"); + + TEST_ASSERT(test_ret_value, + dst == h_expected_dsts[i], + "expected destinations don't match with returned ones"); + } + + cugraph_lookup_result_free(result); + } + +#endif + + cugraph_mg_graph_free(graph); + cugraph_error_free(ret_error); + + return test_ret_value; +} + +int test_lookup_src_dst_test(const cugraph_resource_handle_t* handle) +{ + size_t num_edges = 10; + size_t num_vertices = 5; + + vertex_t h_srcs[] = {7, 1, 1, 2, 1, 8, 3, 4, 0, 0}; + vertex_t h_dsts[] = {8, 3, 4, 0, 0, 7, 1, 1, 2, 1}; + + edge_t h_edge_ids[] = {78, 13, 14, 20, 10, 78, 13, 14, 20, 10}; + + edge_type_t h_edge_types[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2}; + + edge_t edge_ids_to_lookup[] = {10, 12, 78, 78}; + edge_t edge_types_to_lookup[] = {2, 0, 0, 2}; + + // expected results + vertex_t h_expected_srcs[] = {0, -1, 7, -1}; + vertex_t h_expected_dsts[] = {1, -1, 8, -1}; + size_t num_edge_ids_to_lookup = 4; + + return generic_lookup_src_dst_test(handle, + h_srcs, + h_dsts, + h_edge_ids, + h_edge_types, + num_vertices, + num_edges, + FALSE, + edge_ids_to_lookup, + edge_types_to_lookup, + num_edge_ids_to_lookup, + h_expected_srcs, + h_expected_dsts); + + return 0; +} + +/******************************************************************************/ + +int main(int argc, char** argv) +{ + void* raft_handle = create_mg_raft_handle(argc, argv); + cugraph_resource_handle_t* handle = cugraph_create_resource_handle(raft_handle); + + int result = 0; + result |= RUN_MG_TEST(test_lookup_src_dst_test, handle); + + cugraph_free_resource_handle(handle); + free_mg_raft_handle(raft_handle); + + return result; +} diff --git a/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd b/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd index 7348b35fc98..b8efdc7f5a4 100644 --- a/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd +++ b/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd @@ -33,32 +33,38 @@ from pylibcugraph._cugraph_c.graph cimport ( cdef extern from "cugraph_c/lookup_src_dst.h": ########################################################################### - ctypedef struct lookup_container_t: + ctypedef struct cugraph_lookup_container_t: pass - ctypedef struct lookup_result_t: + ctypedef struct cugraph_lookup_result_t: pass cdef cugraph_error_code_t cugraph_build_edge_id_and_type_to_src_dst_lookup_map( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - lookup_container_t** lookup_container, + cugraph_lookup_container_t** lookup_container, cugraph_error_t** error) cdef cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_single_type( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - const lookup_container_t* lookup_container, + const cugraph_lookup_container_t* lookup_container, const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, int edge_type_to_lookup, - lookup_result_t** result, + cugraph_lookup_result_t** result, cugraph_error_t** error) cdef cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types( const cugraph_resource_handle_t* handle, cugraph_graph_t* graph, - const lookup_container_t* lookup_container, + const cugraph_lookup_container_t* lookup_container, const cugraph_type_erased_device_array_view_t* edge_ids_to_lookup, const cugraph_type_erased_device_array_view_t* edge_types_to_lookup, - lookup_result_t** result, + cugraph_lookup_result_t** result, cugraph_error_t** error) + + cdef cugraph_type_erased_device_array_view_t* cugraph_lookup_result_get_srcs( + const cugraph_lookup_result_t* result) + + cdef cugraph_type_erased_device_array_view_t* cugraph_lookup_result_get_dsts( + const cugraph_lookup_result_t* result) From cd592c69619ac068e61c6c0179e3d0baa85941d9 Mon Sep 17 00:00:00 2001 From: Naim Date: Tue, 25 Jun 2024 01:43:41 +0200 Subject: [PATCH 24/26] Add function to delete result --- cpp/src/c_api/lookup_src_dst.cpp | 2 -- cpp/src/c_api/lookup_src_dst.hpp | 2 -- python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd | 2 ++ 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cpp/src/c_api/lookup_src_dst.cpp b/cpp/src/c_api/lookup_src_dst.cpp index 25a9fb78ebc..f805a9f72f1 100644 --- a/cpp/src/c_api/lookup_src_dst.cpp +++ b/cpp/src/c_api/lookup_src_dst.cpp @@ -22,8 +22,6 @@ #include "c_api/resource_handle.hpp" #include "c_api/utils.hpp" -// #include -// #include #include #include diff --git a/cpp/src/c_api/lookup_src_dst.hpp b/cpp/src/c_api/lookup_src_dst.hpp index bfd6213093b..9dad3a59b97 100644 --- a/cpp/src/c_api/lookup_src_dst.hpp +++ b/cpp/src/c_api/lookup_src_dst.hpp @@ -18,8 +18,6 @@ #include "c_api/array.hpp" #include "c_api/error.hpp" -// #include - #include #include diff --git a/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd b/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd index b8efdc7f5a4..710ca7d113b 100644 --- a/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd +++ b/python/pylibcugraph/pylibcugraph/_cugraph_c/lookup_src_dst.pxd @@ -68,3 +68,5 @@ cdef extern from "cugraph_c/lookup_src_dst.h": cdef cugraph_type_erased_device_array_view_t* cugraph_lookup_result_get_dsts( const cugraph_lookup_result_t* result) + + cdef void cugraph_lookup_result_free(cugraph_lookup_result_t* result) From 8fd4c8577a02b1db7c5f99ff9041c093e73aa6fc Mon Sep 17 00:00:00 2001 From: Naim Date: Tue, 25 Jun 2024 20:45:30 +0200 Subject: [PATCH 25/26] Fix bug in C API --- cpp/src/c_api/lookup_src_dst.cpp | 81 ++++++++++++++++-------- cpp/tests/c_api/mg_lookup_src_dst_test.c | 62 +++++++++++++++--- 2 files changed, 106 insertions(+), 37 deletions(-) diff --git a/cpp/src/c_api/lookup_src_dst.cpp b/cpp/src/c_api/lookup_src_dst.cpp index f805a9f72f1..29d100dae31 100644 --- a/cpp/src/c_api/lookup_src_dst.cpp +++ b/cpp/src/c_api/lookup_src_dst.cpp @@ -74,30 +74,23 @@ struct build_lookup_map_functor : public cugraph::c_api::abstract_functor { auto edge_ids = reinterpret_cast< cugraph::edge_property_t, - edge_t>*>(graph_->edge_type_); + edge_t>*>(graph_->edge_ids_); + auto edge_types = reinterpret_cast< cugraph::edge_property_t, - edge_type_type_t>*>(graph_->edge_type_id_type_); + edge_type_type_t>*>(graph_->edge_types_); - auto number_map = reinterpret_cast*>(graph_->number_map_); + auto renumber_map = reinterpret_cast*>(graph_->number_map_); auto lookup_container = new cugraph::lookup_container_t(); - std::cout << "\n\nGoing to call cugraph::build_edge_id_and_type_to_src_dst_lookup_map\n\n"; - - cugraph::build_edge_id_and_type_to_src_dst_lookup_map( - handle_, graph_view, edge_ids->view(), edge_types->view()); + *lookup_container = std::move(cugraph::build_edge_id_and_type_to_src_dst_lookup_map( + handle_, graph_view, edge_ids->view(), edge_types->view())); - std::cout << "\n\nAfter calling cugraph::build_edge_id_and_type_to_src_dst_lookup_map\n\n"; - /* - *lookup_container = std::move(cugraph::build_edge_id_and_type_to_src_dst_lookup_map( - handle_, graph_view, edge_ids->view(), edge_types->view())); + auto result = new cugraph::c_api::cugraph_lookup_container_t{ + graph_->edge_type_, graph_->edge_type_id_type_, graph_->vertex_type_, lookup_container}; - auto result = new cugraph::c_api::cugraph_lookup_container_t{ - graph_->edge_type_, graph_->edge_type_id_type_, graph_->vertex_type_, lookup_container}; - - result_ = reinterpret_cast(result); - */ + result_ = reinterpret_cast(result); } } }; @@ -165,12 +158,31 @@ struct lookup_using_edge_ids_of_single_type_functor : public cugraph::c_api::abs edge_ids_to_lookup_->size_), edge_type_to_lookup_); - auto number_map = reinterpret_cast*>(graph_->number_map_); + auto renumber_map = reinterpret_cast*>(graph_->number_map_); + + auto result_srcs = std::move(std::get<0>(result)); + auto result_dsts = std::move(std::get<1>(result)); + + cugraph::unrenumber_int_vertices( + handle_, + result_srcs.data(), + result_srcs.size(), + renumber_map->data(), + graph_view.vertex_partition_range_lasts(), + false); + + cugraph::unrenumber_int_vertices( + handle_, + result_dsts.data(), + result_dsts.size(), + renumber_map->data(), + graph_view.vertex_partition_range_lasts(), + false); result_ = new cugraph::c_api::cugraph_lookup_result_t{ - new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<0>(result), + new cugraph::c_api::cugraph_type_erased_device_array_t(result_srcs, lookup_container_->vertex_type_), - new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<1>(result), + new cugraph::c_api::cugraph_type_erased_device_array_t(result_dsts, lookup_container_->vertex_type_)}; } } @@ -241,12 +253,31 @@ struct lookup_using_edge_ids_and_types_functor : public cugraph::c_api::abstract raft::device_span( edge_types_to_lookup_->as_type(), edge_types_to_lookup_->size_)); - auto number_map = reinterpret_cast*>(graph_->number_map_); + auto renumber_map = reinterpret_cast*>(graph_->number_map_); + + auto result_srcs = std::move(std::get<0>(result)); + auto result_dsts = std::move(std::get<1>(result)); + + cugraph::unrenumber_int_vertices( + handle_, + result_srcs.data(), + result_srcs.size(), + renumber_map->data(), + graph_view.vertex_partition_range_lasts(), + false); + + cugraph::unrenumber_int_vertices( + handle_, + result_dsts.data(), + result_dsts.size(), + renumber_map->data(), + graph_view.vertex_partition_range_lasts(), + false); result_ = new cugraph::c_api::cugraph_lookup_result_t{ - new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<0>(result), + new cugraph::c_api::cugraph_type_erased_device_array_t(result_srcs, lookup_container_->vertex_type_), - new cugraph::c_api::cugraph_type_erased_device_array_t(std::get<1>(result), + new cugraph::c_api::cugraph_type_erased_device_array_t(result_dsts, lookup_container_->vertex_type_)}; } } @@ -260,11 +291,9 @@ extern "C" cugraph_error_code_t cugraph_build_edge_id_and_type_to_src_dst_lookup cugraph_lookup_container_t** lookup_container, cugraph_error_t** error) { - std::cout << "\nbefore functor\n"; build_lookup_map_functor functor(handle, graph); - std::cout << "\nafter functor, bfore run algo\n"; + return cugraph::c_api::run_algorithm(graph, functor, lookup_container, error); - std::cout << "\nafter run algo\n"; } extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types( @@ -278,7 +307,6 @@ extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types { lookup_using_edge_ids_and_types_functor functor( handle, graph, lookup_container, edge_ids_to_lookup, edge_types_to_lookup); - return cugraph::c_api::run_algorithm(graph, functor, result, error); } @@ -293,7 +321,6 @@ extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_singl { lookup_using_edge_ids_of_single_type_functor functor( handle, graph, lookup_container, edge_ids_to_lookup, edge_type_to_lookup); - return cugraph::c_api::run_algorithm(graph, functor, result, error); } diff --git a/cpp/tests/c_api/mg_lookup_src_dst_test.c b/cpp/tests/c_api/mg_lookup_src_dst_test.c index 83330e0b335..0cffffeb425 100644 --- a/cpp/tests/c_api/mg_lookup_src_dst_test.c +++ b/cpp/tests/c_api/mg_lookup_src_dst_test.c @@ -86,7 +86,6 @@ int generic_lookup_src_dst_test(const cugraph_resource_handle_t* handle, TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); TEST_ALWAYS_ASSERT(ret_code == CUGRAPH_SUCCESS, "cugraph_ecg failed."); -#if 0 cugraph_type_erased_device_array_t* d_edge_ids_to_lookup = NULL; cugraph_type_erased_device_array_view_t* d_edge_ids_to_lookup_view = NULL; @@ -146,23 +145,66 @@ int generic_lookup_src_dst_test(const cugraph_resource_handle_t* handle, "number of edges in returned result") for (int i = 0; i < num_edge_ids_to_lookup; i++) { - printf("\n %d %d\n", h_result_srcs[i], h_result_dsts[i]); vertex_t src = (h_result_srcs[i] < h_result_dsts[i]) ? h_result_srcs[i] : h_result_dsts[i]; vertex_t dst = (h_result_srcs[i] >= h_result_dsts[i]) ? h_result_srcs[i] : h_result_dsts[i]; - printf("\n%d %d\n", src, dst); TEST_ASSERT(test_ret_value, src == h_expected_srcs[i], "expected sources don't match with returned ones"); - TEST_ASSERT(test_ret_value, dst == h_expected_dsts[i], "expected destinations don't match with returned ones"); } + } + + cugraph_lookup_result_free(result); + + ret_code = cugraph_lookup_endpoints_from_edge_ids_and_single_type(handle, + graph, + lookup_container, + d_edge_ids_to_lookup_view, + edge_types_to_lookup[0], + &result, + &ret_error); + + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); + TEST_ALWAYS_ASSERT(ret_code == CUGRAPH_SUCCESS, "cugraph_ecg failed."); + + if (test_ret_value == 0) { + cugraph_type_erased_device_array_view_t* d_srcs; + cugraph_type_erased_device_array_view_t* d_dsts; + + d_srcs = cugraph_lookup_result_get_srcs(result); + d_dsts = cugraph_lookup_result_get_dsts(result); + + vertex_t h_result_srcs[num_edge_ids_to_lookup]; + edge_t h_result_dsts[num_edge_ids_to_lookup]; + + ret_code = cugraph_type_erased_device_array_view_copy_to_host( + handle, (byte_t*)h_result_srcs, d_srcs, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); + + ret_code = cugraph_type_erased_device_array_view_copy_to_host( + handle, (byte_t*)h_result_dsts, d_dsts, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); + + size_t result_num_edges = cugraph_type_erased_device_array_view_size(d_srcs); + + TEST_ALWAYS_ASSERT(result_num_edges == num_edge_ids_to_lookup, + "number of edges in returned result") - cugraph_lookup_result_free(result); + for (int i = 0; i < num_edge_ids_to_lookup; i++) { + vertex_t src = (h_result_srcs[i] < h_result_dsts[i]) ? h_result_srcs[i] : h_result_dsts[i]; + vertex_t dst = (h_result_srcs[i] >= h_result_dsts[i]) ? h_result_srcs[i] : h_result_dsts[i]; + TEST_ASSERT(test_ret_value, + src == h_expected_srcs[i], + "expected sources don't match with returned ones"); + TEST_ASSERT(test_ret_value, + dst == h_expected_dsts[i], + "expected destinations don't match with returned ones"); + } } -#endif + cugraph_lookup_result_free(result); cugraph_mg_graph_free(graph); cugraph_error_free(ret_error); @@ -182,12 +224,12 @@ int test_lookup_src_dst_test(const cugraph_resource_handle_t* handle) edge_type_t h_edge_types[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2}; - edge_t edge_ids_to_lookup[] = {10, 12, 78, 78}; - edge_t edge_types_to_lookup[] = {2, 0, 0, 2}; + edge_t edge_ids_to_lookup[] = {10, 12, 78, 20}; + edge_t edge_types_to_lookup[] = {2, 0, 3, 2}; // expected results - vertex_t h_expected_srcs[] = {0, -1, 7, -1}; - vertex_t h_expected_dsts[] = {1, -1, 8, -1}; + vertex_t h_expected_srcs[] = {0, -1, -1, 0}; + vertex_t h_expected_dsts[] = {1, -1, -1, 2}; size_t num_edge_ids_to_lookup = 4; return generic_lookup_src_dst_test(handle, From f0e8485def9474717466dd6b0fa09a9111dd988f Mon Sep 17 00:00:00 2001 From: Naim Date: Tue, 2 Jul 2024 19:51:19 +0200 Subject: [PATCH 26/26] Add CAPI_EXPECTS checks --- cpp/src/c_api/lookup_src_dst.cpp | 42 +++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/cpp/src/c_api/lookup_src_dst.cpp b/cpp/src/c_api/lookup_src_dst.cpp index 29d100dae31..1be2137ef2f 100644 --- a/cpp/src/c_api/lookup_src_dst.cpp +++ b/cpp/src/c_api/lookup_src_dst.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024, NVIDIA CORPORATION. + * Copyright (c) 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. @@ -305,6 +305,26 @@ extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_types cugraph_lookup_result_t** result, cugraph_error_t** error) { + CAPI_EXPECTS( + reinterpret_cast(graph)->vertex_type_ == + reinterpret_cast(lookup_container)->vertex_type_, + CUGRAPH_INVALID_INPUT, + "vertex type of graph and lookup_container must match", + *error); + CAPI_EXPECTS( + reinterpret_cast(graph)->edge_type_ == + reinterpret_cast(lookup_container)->edge_type_, + CUGRAPH_INVALID_INPUT, + "edge type of graph and lookup_container must match", + *error); + + CAPI_EXPECTS(reinterpret_cast(graph)->edge_type_id_type_ == + reinterpret_cast(lookup_container) + ->edge_type_id_type_, + CUGRAPH_INVALID_INPUT, + "edge type id type of graph and lookup_container must match", + *error); + lookup_using_edge_ids_and_types_functor functor( handle, graph, lookup_container, edge_ids_to_lookup, edge_types_to_lookup); return cugraph::c_api::run_algorithm(graph, functor, result, error); @@ -319,6 +339,26 @@ extern "C" cugraph_error_code_t cugraph_lookup_endpoints_from_edge_ids_and_singl cugraph_lookup_result_t** result, cugraph_error_t** error) { + CAPI_EXPECTS( + reinterpret_cast(graph)->vertex_type_ == + reinterpret_cast(lookup_container)->vertex_type_, + CUGRAPH_INVALID_INPUT, + "vertex type of graph and lookup_container must match", + *error); + CAPI_EXPECTS( + reinterpret_cast(graph)->edge_type_ == + reinterpret_cast(lookup_container)->edge_type_, + CUGRAPH_INVALID_INPUT, + "edge type of graph and lookup_container must match", + *error); + + CAPI_EXPECTS(reinterpret_cast(graph)->edge_type_id_type_ == + reinterpret_cast(lookup_container) + ->edge_type_id_type_, + CUGRAPH_INVALID_INPUT, + "edge type id type of graph and lookup_container must match", + *error); + lookup_using_edge_ids_of_single_type_functor functor( handle, graph, lookup_container, edge_ids_to_lookup, edge_type_to_lookup); return cugraph::c_api::run_algorithm(graph, functor, result, error);