From a838fc5292cf6e68c56e7d17c078d3ea21b279da Mon Sep 17 00:00:00 2001 From: Charles Blackmon-Luca <20627856+charlesbluca@users.noreply.github.com> Date: Wed, 13 Apr 2022 09:11:15 -0400 Subject: [PATCH 1/4] Make diagram and caption consistent in Pagerank.ipynb (#2207) Fixes some small inconsistencies between code blocks / diagrams and their associated captions in the Pagerank notebook. We might want to resolve the FutureWarning raised in `from_cudf_edgelist` first, as it crops up in the outputs (xref https://github.com/rapidsai/cugraph/issues/2174). Closes #2182 Authors: - Charles Blackmon-Luca (https://github.com/charlesbluca) Approvers: - Brad Rees (https://github.com/BradReesWork) URL: https://github.com/rapidsai/cugraph/pull/2207 --- notebooks/link_analysis/Pagerank.ipynb | 117 ++++++++++++++----------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/notebooks/link_analysis/Pagerank.ipynb b/notebooks/link_analysis/Pagerank.ipynb index 3debb9fab9a..30b637613b5 100755 --- a/notebooks/link_analysis/Pagerank.ipynb +++ b/notebooks/link_analysis/Pagerank.ipynb @@ -2,7 +2,9 @@ "cells": [ { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "tags": [] + }, "source": [ "# PageRank\n", "\n", @@ -11,13 +13,13 @@ "Notebook Credits\n", "* Original Authors: Bradley Rees and James Wyles\n", "* Created: 08/13/2019\n", - "* Updated: 01/17/2021\n", + "* Updated: 04/06/2022\n", "\n", - "RAPIDS Versions: 0.14 \n", + "RAPIDS Versions: 22.04 \n", "\n", "Test Hardware\n", "\n", - "* GV100 32G, CUDA 10.0\n", + "* GV100 32G, CUDA 11.5\n", "\n", "\n", "## Introduction\n", @@ -75,9 +77,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: networkx in /home/brad/anaconda3/envs/cugraph_dev/lib/python3.8/site-packages (2.6.2)\n", - "Requirement already satisfied: scipy in /home/brad/anaconda3/envs/cugraph_dev/lib/python3.8/site-packages (1.7.0)\n", - "Requirement already satisfied: numpy<1.23.0,>=1.16.5 in /home/brad/anaconda3/envs/cugraph_dev/lib/python3.8/site-packages (from scipy) (1.21.1)\n" + "Requirement already satisfied: networkx in /opt/conda/envs/rapids/lib/python3.9/site-packages (2.6.3)\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0mRequirement already satisfied: scipy in /opt/conda/envs/rapids/lib/python3.9/site-packages (1.6.0)\n", + "Requirement already satisfied: numpy>=1.16.5 in /opt/conda/envs/rapids/lib/python3.9/site-packages (from scipy) (1.21.5)\n", + "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n", + "\u001b[0m" ] } ], @@ -270,7 +275,16 @@ "cell_type": "code", "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/opt/conda/envs/rapids/lib/python3.9/site-packages/cudf/core/indexed_frame.py:2271: FutureWarning: append is deprecated and will be removed in a future version. Use concat instead.\n", + " warnings.warn(\n" + ] + } + ], "source": [ "# create a Graph using the source (src) and destination (dst) vertex pairs from the Dataframe \n", "G = cugraph.from_edgelist(gdf, source='src', destination='dst')" @@ -315,7 +329,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Best vertex is 34 with score of 0.10091734\n" + "Best vertex is 34 with score of 0.100917324\n" ] } ], @@ -373,7 +387,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Best vertex is 34 with score of 0.10091734\n" + "Best vertex is 34 with score of 0.100917324\n" ] } ], @@ -433,17 +447,17 @@ " \n", " \n", " \n", - " 2\n", + " 16\n", " 0.100917\n", " 34\n", " \n", " \n", - " 3\n", + " 17\n", " 0.096999\n", " 1\n", " \n", " \n", - " 4\n", + " 18\n", " 0.071692\n", " 33\n", " \n", @@ -452,10 +466,10 @@ "" ], "text/plain": [ - " pagerank vertex\n", - "2 0.100917 34\n", - "3 0.096999 1\n", - "4 0.071692 33" + " pagerank vertex\n", + "16 0.100917 34\n", + "17 0.096999 1\n", + "18 0.071692 33" ] }, "execution_count": 17, @@ -517,39 +531,32 @@ " \n", " \n", " \n", - " 2\n", + " 16\n", " 17\n", " 17\n", " 34\n", " \n", " \n", - " 3\n", + " 17\n", " 16\n", " 16\n", " 1\n", " \n", " \n", - " 4\n", + " 18\n", " 12\n", " 12\n", " 33\n", " \n", - " \n", - " 5\n", - " 10\n", - " 10\n", - " 3\n", - " \n", " \n", "\n", "" ], "text/plain": [ - " in_degree out_degree vertex\n", - "2 17 17 34\n", - "3 16 16 1\n", - "4 12 12 33\n", - "5 10 10 3" + " in_degree out_degree vertex\n", + "16 17 17 34\n", + "17 16 16 1\n", + "18 12 12 33" ] }, "execution_count": 19, @@ -558,7 +565,7 @@ } ], "source": [ - "d.sort_values('out_degree', ascending=False).head(4)" + "d.sort_values('out_degree', ascending=False).head(3)" ] }, { @@ -585,7 +592,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -597,7 +604,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -606,7 +613,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -636,17 +643,17 @@ " \n", " \n", " \n", - " 22\n", + " 4\n", " 0.121756\n", " 26\n", " \n", " \n", - " 28\n", + " 10\n", " 0.085409\n", " 17\n", " \n", " \n", - " 3\n", + " 17\n", " 0.077714\n", " 1\n", " \n", @@ -656,12 +663,12 @@ ], "text/plain": [ " pagerank vertex\n", - "22 0.121756 26\n", - "28 0.085409 17\n", - "3 0.077714 1" + "4 0.121756 26\n", + "10 0.085409 17\n", + "17 0.077714 1" ] }, - "execution_count": 28, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -672,7 +679,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -702,33 +709,39 @@ " \n", " \n", " \n", - " 22\n", + " 4\n", " 0.021006\n", " 26\n", " \n", " \n", - " 28\n", + " 10\n", " 0.016785\n", " 17\n", " \n", + " \n", + " 17\n", + " 0.096999\n", + " 1\n", + " \n", " \n", "\n", "" ], "text/plain": [ " pagerank vertex\n", - "22 0.021006 26\n", - "28 0.016785 17" + "4 0.021006 26\n", + "10 0.016785 17\n", + "17 0.096999 1" ] }, - "execution_count": 29, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# looking at the initial PageRank values\n", - "gdf_page[gdf_page['vertex'].isin([17,26])]" + "gdf_page[gdf_page['vertex'].isin([26,17,1])]" ] }, { @@ -747,9 +760,9 @@ ], "metadata": { "kernelspec": { - "display_name": "cugraph_dev", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "cugraph_dev" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -761,7 +774,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.9.7" } }, "nbformat": 4, From 5b5cd90dc4a935bd8aca84e67f0623562242f39b Mon Sep 17 00:00:00 2001 From: Chuck Hastings <45364586+ChuckHastings@users.noreply.github.com> Date: Wed, 13 Apr 2022 09:32:04 -0400 Subject: [PATCH 2/4] Labeling algorithm updates for C API (#2185) Several things bundled here: * Added C API definition, implementation and tests for weakly connected components * Added C API definition for strongly connected components * Updated the C API test functions for supporting the `is_symmetric` property * Added C unit tests for SCC, and an implementation that returns `NOT_IMPLEMENTED` I could add some mock data returns, although the output from SCC is the same as the output from WCC. So python testing could just call WCC instead until there is an SCC implementation. Authors: - Chuck Hastings (https://github.com/ChuckHastings) Approvers: - Seunghwa Kang (https://github.com/seunghwak) URL: https://github.com/rapidsai/cugraph/pull/2185 --- cpp/CMakeLists.txt | 3 + cpp/include/cugraph_c/algorithms.h | 2 + cpp/include/cugraph_c/labeling_algorithms.h | 101 +++++++++++ cpp/src/c_api/katz.cpp | 2 +- cpp/src/c_api/labeling_result.cpp | 43 +++++ cpp/src/c_api/labeling_result.hpp | 30 ++++ .../c_api/strongly_connected_components.cpp | 86 ++++++++++ cpp/src/c_api/weakly_connected_components.cpp | 105 ++++++++++++ cpp/tests/CMakeLists.txt | 4 + cpp/tests/c_api/bfs_test.c | 10 +- cpp/tests/c_api/c_test_utils.h | 1 + cpp/tests/c_api/eigenvector_centrality_test.c | 2 +- cpp/tests/c_api/extract_paths_test.c | 2 +- cpp/tests/c_api/hits_test.c | 2 +- cpp/tests/c_api/katz_test.c | 2 +- .../c_api/mg_eigenvector_centrality_test.c | 49 +++--- cpp/tests/c_api/mg_hits_test.c | 44 +++-- cpp/tests/c_api/mg_katz_test.c | 2 +- cpp/tests/c_api/mg_pagerank_test.c | 10 +- .../mg_strongly_connected_components_test.c | 159 ++++++++++++++++++ cpp/tests/c_api/mg_test_utils.cpp | 3 +- cpp/tests/c_api/mg_test_utils.h | 1 + .../c_api/mg_uniform_neighbor_sample_test.c | 2 +- .../mg_weakly_connected_components_test.c | 156 +++++++++++++++++ cpp/tests/c_api/node2vec_test.c | 2 +- cpp/tests/c_api/pagerank_test.c | 2 +- cpp/tests/c_api/sssp_test.c | 2 +- .../strongly_connected_components_test.c | 131 +++++++++++++++ cpp/tests/c_api/test_utils.cpp | 3 +- .../c_api/uniform_neighbor_sample_test.c | 2 +- .../c_api/weakly_connected_components_test.c | 127 ++++++++++++++ 31 files changed, 1029 insertions(+), 61 deletions(-) create mode 100644 cpp/include/cugraph_c/labeling_algorithms.h create mode 100644 cpp/src/c_api/labeling_result.cpp create mode 100644 cpp/src/c_api/labeling_result.hpp create mode 100644 cpp/src/c_api/strongly_connected_components.cpp create mode 100644 cpp/src/c_api/weakly_connected_components.cpp create mode 100644 cpp/tests/c_api/mg_strongly_connected_components_test.c create mode 100644 cpp/tests/c_api/mg_weakly_connected_components_test.c create mode 100644 cpp/tests/c_api/strongly_connected_components_test.c create mode 100644 cpp/tests/c_api/weakly_connected_components_test.c diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index f04ba70abef..14440e20892 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -366,6 +366,9 @@ add_library(cugraph_c src/c_api/extract_paths.cpp src/c_api/random_walks.cpp src/c_api/uniform_neighbor_sampling.cpp + src/c_api/labeling_result.cpp + src/c_api/weakly_connected_components.cpp + src/c_api/strongly_connected_components.cpp ) add_library(cugraph::cugraph_c ALIAS cugraph_c) diff --git a/cpp/include/cugraph_c/algorithms.h b/cpp/include/cugraph_c/algorithms.h index 8e1c4558887..aa4ff518603 100644 --- a/cpp/include/cugraph_c/algorithms.h +++ b/cpp/include/cugraph_c/algorithms.h @@ -373,3 +373,5 @@ void cugraph_sample_result_free(cugraph_sample_result_t* result); #ifdef __cplusplus } #endif + +#include diff --git a/cpp/include/cugraph_c/labeling_algorithms.h b/cpp/include/cugraph_c/labeling_algorithms.h new file mode 100644 index 00000000000..1ad835e2593 --- /dev/null +++ b/cpp/include/cugraph_c/labeling_algorithms.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022, 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 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Opaque labeling result type + */ +typedef struct { + int32_t align_; +} cugraph_labeling_result_t; + +/** + * @brief Get the vertex ids from the labeling result + * + * @param [in] result The result from a labeling algorithm + * @return type erased array of vertex ids + */ +cugraph_type_erased_device_array_view_t* cugraph_labeling_result_get_vertices( + cugraph_labeling_result_t* result); + +/** + * @brief Get the label values from the labeling result + * + * @param [in] result The result from a labeling algorithm + * @return type erased array of label values + */ +cugraph_type_erased_device_array_view_t* cugraph_labeling_result_get_labels( + cugraph_labeling_result_t* result); + +/** + * @brief Free labeling result + * + * @param [in] result The result from a labeling algorithm + */ +void cugraph_labeling_result_free(cugraph_labeling_result_t* result); + +/** + * @brief Labels each vertex in the input graph with its (weakly-connected-)component ID + * + * The input graph must be symmetric. Component IDs can be arbitrary integers (they can be + * non-consecutive and are not ordered by component size or any other criterion). + * + * @param [in] handle Handle for accessing resources + * @param [in] graph Pointer to graph + * @param [in] do_expensive_check A flag to run expensive checks for input arguments (if set to + * `true`). + * @param [out] result Opaque pointer to labeling results + * @param [out] error Pointer to an error object storing details of any error. Will + * be populated if error code is not CUGRAPH_SUCCESS + */ +cugraph_error_code_t cugraph_weakly_connected_components(const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + bool_t do_expensive_check, + cugraph_labeling_result_t** result, + cugraph_error_t** error); + +/** + * @brief Labels each vertex in the input graph with its (strongly-connected-)component ID + * + * The input graph may be asymmetric. Component IDs can be arbitrary integers (they can be + * non-consecutive and are not ordered by component size or any other criterion). + * + * @param [in] handle Handle for accessing resources + * @param [in] graph Pointer to graph + * @param [in] do_expensive_check A flag to run expensive checks for input arguments (if set to + * `true`). + * @param [out] result Opaque pointer to labeling results + * @param [out] error Pointer to an error object storing details of any error. Will + * be populated if error code is not CUGRAPH_SUCCESS + */ +cugraph_error_code_t cugraph_strongly_connected_components(const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + bool_t do_expensive_check, + cugraph_labeling_result_t** result, + cugraph_error_t** error); + +#ifdef __cplusplus +} +#endif diff --git a/cpp/src/c_api/katz.cpp b/cpp/src/c_api/katz.cpp index 960bae505bc..e9b92f7f758 100644 --- a/cpp/src/c_api/katz.cpp +++ b/cpp/src/c_api/katz.cpp @@ -98,7 +98,7 @@ struct katz_functor : public cugraph::c_api::abstract_functor { cugraph::detail::sequence_fill(handle_.get_stream(), betas_vertex_ids.data(), betas_vertex_ids.size(), - graph_view.local_vertex_partition_range_size()); + graph_view.local_vertex_partition_range_first()); betas.resize(graph_view.local_vertex_partition_range_size(), handle_.get_stream()); diff --git a/cpp/src/c_api/labeling_result.cpp b/cpp/src/c_api/labeling_result.cpp new file mode 100644 index 00000000000..f4fb3e324fd --- /dev/null +++ b/cpp/src/c_api/labeling_result.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022, 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 + +#include + +extern "C" cugraph_type_erased_device_array_view_t* cugraph_labeling_result_get_vertices( + cugraph_labeling_result_t* result) +{ + auto internal_pointer = reinterpret_cast(result); + return reinterpret_cast( + internal_pointer->vertex_ids_->view()); +} + +extern "C" cugraph_type_erased_device_array_view_t* cugraph_labeling_result_get_labels( + cugraph_labeling_result_t* result) +{ + auto internal_pointer = reinterpret_cast(result); + return reinterpret_cast( + internal_pointer->labels_->view()); +} + +extern "C" void cugraph_labeling_result_free(cugraph_labeling_result_t* result) +{ + auto internal_pointer = reinterpret_cast(result); + delete internal_pointer->vertex_ids_; + delete internal_pointer->labels_; + delete internal_pointer; +} diff --git a/cpp/src/c_api/labeling_result.hpp b/cpp/src/c_api/labeling_result.hpp new file mode 100644 index 00000000000..4adeb5c3219 --- /dev/null +++ b/cpp/src/c_api/labeling_result.hpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, 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 + +namespace cugraph { +namespace c_api { + +struct cugraph_labeling_result_t { + cugraph_type_erased_device_array_t* vertex_ids_; + cugraph_type_erased_device_array_t* labels_; +}; + +} // namespace c_api +} // namespace cugraph diff --git a/cpp/src/c_api/strongly_connected_components.cpp b/cpp/src/c_api/strongly_connected_components.cpp new file mode 100644 index 00000000000..e8bbfcb3886 --- /dev/null +++ b/cpp/src/c_api/strongly_connected_components.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2022, 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace { + +struct scc_functor : public cugraph::c_api::abstract_functor { + raft::handle_t const& handle_; + cugraph::c_api::cugraph_graph_t* graph_{}; + bool do_expensive_check_{}; + cugraph::c_api::cugraph_labeling_result_t* result_{}; + + scc_functor(::cugraph_resource_handle_t const* handle, + ::cugraph_graph_t* graph, + bool do_expensive_check) + : abstract_functor(), + handle_(*reinterpret_cast(handle)->handle_), + graph_(reinterpret_cast(graph)), + do_expensive_check_(do_expensive_check) + { + } + + template + void operator()() + { + if constexpr (!cugraph::is_candidate::value) { + unsupported(); + } else { + // SCC 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; + } + + error_code_ = CUGRAPH_NOT_IMPLEMENTED; + error_->error_message_ = "SCC Not currently implemented"; + } + } +}; + +} // namespace + +extern "C" cugraph_error_code_t cugraph_strongly_connected_components( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + bool_t do_expensive_check, + cugraph_labeling_result_t** result, + cugraph_error_t** error) +{ + scc_functor functor(handle, graph, do_expensive_check); + + return cugraph::c_api::run_algorithm(graph, functor, result, error); +} diff --git a/cpp/src/c_api/weakly_connected_components.cpp b/cpp/src/c_api/weakly_connected_components.cpp new file mode 100644 index 00000000000..9625ad129a5 --- /dev/null +++ b/cpp/src/c_api/weakly_connected_components.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022, 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace { + +struct wcc_functor : public cugraph::c_api::abstract_functor { + raft::handle_t const& handle_; + cugraph::c_api::cugraph_graph_t* graph_{}; + bool do_expensive_check_{}; + cugraph::c_api::cugraph_labeling_result_t* result_{}; + + wcc_functor(cugraph_resource_handle_t const* handle, + cugraph_graph_t* graph, + bool do_expensive_check) + : abstract_functor(), + handle_(*reinterpret_cast(handle)->handle_), + graph_(reinterpret_cast(graph)), + do_expensive_check_(do_expensive_check) + { + } + + template + void operator()() + { + if constexpr (!cugraph::is_candidate::value) { + unsupported(); + } else { + // WCC 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 number_map = reinterpret_cast*>(graph_->number_map_); + + rmm::device_uvector components(graph_view.local_vertex_partition_range_size(), + handle_.get_stream()); + + cugraph::weakly_connected_components( + handle_, graph_view, components.data(), do_expensive_check_); + + rmm::device_uvector vertex_ids(graph_view.local_vertex_partition_range_size(), + handle_.get_stream()); + raft::copy(vertex_ids.data(), number_map->data(), vertex_ids.size(), handle_.get_stream()); + + result_ = new cugraph::c_api::cugraph_labeling_result_t{ + new cugraph::c_api::cugraph_type_erased_device_array_t(vertex_ids, graph_->vertex_type_), + new cugraph::c_api::cugraph_type_erased_device_array_t(components, graph_->vertex_type_)}; + } + } +}; + +} // namespace + +extern "C" cugraph_error_code_t cugraph_weakly_connected_components( + const cugraph_resource_handle_t* handle, + cugraph_graph_t* graph, + bool_t do_expensive_check, + cugraph_labeling_result_t** result, + cugraph_error_t** error) +{ + wcc_functor functor(handle, graph, do_expensive_check); + + return cugraph::c_api::run_algorithm(graph, functor, result, error); +} diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index a0665f4e29e..2b3caf5ee49 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -620,6 +620,8 @@ if(BUILD_CUGRAPH_MG_TESTS) # - MG C API tests ------------------------------------------------------------------------ ConfigureCTestMG(MG_CAPI_CREATE_GRAPH c_api/mg_create_graph_test.c c_api/mg_test_utils.cpp) ConfigureCTestMG(MG_CAPI_PAGERANK c_api/mg_pagerank_test.c c_api/mg_test_utils.cpp) + ConfigureCTestMG(MG_CAPI_WEAKLY_CONNECTED_COMPONENTS c_api/mg_weakly_connected_components_test.c c_api/mg_test_utils.cpp) + ConfigureCTestMG(MG_CAPI_STRONGLY_CONNECTED_COMPONENTS c_api/mg_strongly_connected_components_test.c c_api/mg_test_utils.cpp) ConfigureCTestMG(MG_CAPI_KATZ c_api/mg_katz_test.c c_api/mg_test_utils.cpp) ConfigureCTestMG(MG_CAPI_EIGENVECTOR_CENTRALITY c_api/mg_eigenvector_centrality_test.c c_api/mg_test_utils.cpp) ConfigureCTestMG(MG_CAPI_HITS c_api/mg_hits_test.c c_api/mg_test_utils.cpp) @@ -671,6 +673,8 @@ ConfigureCTest(CAPI_BFS_TEST c_api/bfs_test.c) ConfigureCTest(CAPI_SSSP_TEST c_api/sssp_test.c) ConfigureCTest(CAPI_EXTRACT_PATHS_TEST c_api/extract_paths_test.c) ConfigureCTest(CAPI_NODE2VEC_TEST c_api/node2vec_test.c) +ConfigureCTest(CAPI_WEAKLY_CONNECTED_COMPONENTS c_api/weakly_connected_components_test.c) +ConfigureCTest(CAPI_STRONGLY_CONNECTED_COMPONENTS c_api/strongly_connected_components_test.c) ConfigureCTest(CAPI_UNIFORM_NEIGHBOR_SAMPLE c_api/uniform_neighbor_sample_test.c) ################################################################################################### diff --git a/cpp/tests/c_api/bfs_test.c b/cpp/tests/c_api/bfs_test.c index 8709e70c8d3..6f13f125df6 100644 --- a/cpp/tests/c_api/bfs_test.c +++ b/cpp/tests/c_api/bfs_test.c @@ -42,17 +42,17 @@ int generic_bfs_test(vertex_t* h_src, cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; cugraph_error_t* ret_error = NULL; - cugraph_resource_handle_t* p_handle = NULL; - cugraph_graph_t* p_graph = NULL; - cugraph_paths_result_t* p_result = NULL; - cugraph_type_erased_device_array_t* p_sources = NULL; + cugraph_resource_handle_t* p_handle = NULL; + cugraph_graph_t* p_graph = NULL; + cugraph_paths_result_t* p_result = NULL; + cugraph_type_erased_device_array_t* p_sources = NULL; cugraph_type_erased_device_array_view_t* p_source_view = NULL; p_handle = cugraph_create_resource_handle(NULL); TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, FALSE, &p_graph, &ret_error); /* * FIXME: in create_graph_test.c, variables are defined but then hard-coded to diff --git a/cpp/tests/c_api/c_test_utils.h b/cpp/tests/c_api/c_test_utils.h index 08d4d25e8ba..206036323a3 100644 --- a/cpp/tests/c_api/c_test_utils.h +++ b/cpp/tests/c_api/c_test_utils.h @@ -50,6 +50,7 @@ int create_test_graph(const cugraph_resource_handle_t* p_handle, size_t num_edges, bool_t store_transposed, bool_t renumber, + bool_t is_symmetric, cugraph_graph_t** p_graph, cugraph_error_t** ret_error); diff --git a/cpp/tests/c_api/eigenvector_centrality_test.c b/cpp/tests/c_api/eigenvector_centrality_test.c index 5e82449b7f4..7127c949d98 100644 --- a/cpp/tests/c_api/eigenvector_centrality_test.c +++ b/cpp/tests/c_api/eigenvector_centrality_test.c @@ -49,7 +49,7 @@ int generic_eigenvector_centrality_test(vertex_t* h_src, TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_test_graph failed."); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); diff --git a/cpp/tests/c_api/extract_paths_test.c b/cpp/tests/c_api/extract_paths_test.c index 65ede81238d..5b87c3151c7 100644 --- a/cpp/tests/c_api/extract_paths_test.c +++ b/cpp/tests/c_api/extract_paths_test.c @@ -57,7 +57,7 @@ int generic_bfs_test_with_extract_paths(vertex_t* h_src, TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, FALSE, &p_graph, &ret_error); ret_code = cugraph_type_erased_device_array_create(p_handle, num_seeds, INT32, &p_sources, &ret_error); diff --git a/cpp/tests/c_api/hits_test.c b/cpp/tests/c_api/hits_test.c index aa53c8e62fc..c275d883d11 100644 --- a/cpp/tests/c_api/hits_test.c +++ b/cpp/tests/c_api/hits_test.c @@ -54,7 +54,7 @@ int generic_hits_test(vertex_t* h_src, TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, renumber, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, renumber, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_test_graph failed."); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); diff --git a/cpp/tests/c_api/katz_test.c b/cpp/tests/c_api/katz_test.c index d5ca6a46643..4ee61b2b806 100644 --- a/cpp/tests/c_api/katz_test.c +++ b/cpp/tests/c_api/katz_test.c @@ -52,7 +52,7 @@ int generic_katz_test(vertex_t* h_src, TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_test_graph failed."); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); diff --git a/cpp/tests/c_api/mg_eigenvector_centrality_test.c b/cpp/tests/c_api/mg_eigenvector_centrality_test.c index d8bf291edef..967f3467963 100644 --- a/cpp/tests/c_api/mg_eigenvector_centrality_test.c +++ b/cpp/tests/c_api/mg_eigenvector_centrality_test.c @@ -26,33 +26,34 @@ typedef int32_t edge_t; typedef float weight_t; int generic_eigenvector_centrality_test(const cugraph_resource_handle_t* handle, - vertex_t* h_src, - vertex_t* h_dst, - weight_t* h_wgt, - weight_t* h_result, - size_t num_vertices, - size_t num_edges, - bool_t store_transposed, - double alpha, - double epsilon, - size_t max_iterations) + vertex_t* h_src, + vertex_t* h_dst, + weight_t* h_wgt, + weight_t* h_result, + size_t num_vertices, + size_t num_edges, + bool_t store_transposed, + double alpha, + double epsilon, + size_t max_iterations) { int test_ret_value = 0; cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; cugraph_error_t* ret_error; - cugraph_graph_t* p_graph = NULL; + cugraph_graph_t* p_graph = NULL; cugraph_centrality_result_t* p_result = NULL; ret_code = create_mg_test_graph( - handle, h_src, h_dst, h_wgt, num_edges, store_transposed, &p_graph, &ret_error); + handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_mg_test_graph failed."); ret_code = cugraph_eigenvector_centrality( handle, p_graph, epsilon, max_iterations, FALSE, &p_result, &ret_error); - TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "cugraph_eigenvector_centrality failed."); + TEST_ASSERT( + test_ret_value, ret_code == CUGRAPH_SUCCESS, "cugraph_eigenvector_centrality failed."); // NOTE: Because we get back vertex ids and centralities, we can simply compare // the returned values with the expected results for the entire @@ -61,7 +62,7 @@ int generic_eigenvector_centrality_test(const cugraph_resource_handle_t* handle, cugraph_type_erased_device_array_view_t* vertices; cugraph_type_erased_device_array_view_t* centralities; - vertices = cugraph_centrality_result_get_vertices(p_result); + vertices = cugraph_centrality_result_get_vertices(p_result); centralities = cugraph_centrality_result_get_values(p_result); vertex_t h_vertices[num_vertices]; @@ -106,16 +107,16 @@ int test_eigenvector_centrality(const cugraph_resource_handle_t* handle) // Pagerank wants store_transposed = TRUE return generic_eigenvector_centrality_test(handle, - h_src, - h_dst, - h_wgt, - h_result, - num_vertices, - num_edges, - TRUE, - alpha, - epsilon, - max_iterations); + h_src, + h_dst, + h_wgt, + h_result, + num_vertices, + num_edges, + TRUE, + alpha, + epsilon, + max_iterations); } /******************************************************************************/ diff --git a/cpp/tests/c_api/mg_hits_test.c b/cpp/tests/c_api/mg_hits_test.c index d69d25a77c7..fb1a7c5451e 100644 --- a/cpp/tests/c_api/mg_hits_test.c +++ b/cpp/tests/c_api/mg_hits_test.c @@ -50,14 +50,22 @@ int generic_hits_test(const cugraph_resource_handle_t* p_handle, cugraph_hits_result_t* p_result = NULL; ret_code = create_mg_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_mg_test_graph failed."); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); if (h_initial_vertices == NULL) { - ret_code = cugraph_hits( - p_handle, p_graph, epsilon, max_iterations, NULL, NULL, normalize, FALSE, &p_result, &ret_error); + ret_code = cugraph_hits(p_handle, + p_graph, + epsilon, + max_iterations, + NULL, + NULL, + normalize, + FALSE, + &p_result, + &ret_error); } else { int rank = cugraph_resource_handle_get_rank(p_handle); @@ -90,8 +98,16 @@ int generic_hits_test(const cugraph_resource_handle_t* p_handle, p_handle, initial_hubs_view, (byte_t*)h_initial_hubs, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "src copy_from_host failed."); - ret_code = cugraph_hits( - p_handle, p_graph, epsilon, max_iterations, initial_vertices_view, initial_hubs_view, normalize, FALSE, &p_result, &ret_error); + ret_code = cugraph_hits(p_handle, + p_graph, + epsilon, + max_iterations, + initial_vertices_view, + initial_hubs_view, + normalize, + FALSE, + &p_result, + &ret_error); } TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "cugraph_hits failed."); @@ -212,17 +228,17 @@ int test_hits_with_transpose(const cugraph_resource_handle_t* handle) int test_hits_with_initial(const cugraph_resource_handle_t* handle) { - size_t num_edges = 8; - size_t num_vertices = 6; + size_t num_edges = 8; + size_t num_vertices = 6; size_t num_initial_hubs = 5; - vertex_t h_src[] = {0, 1, 1, 2, 2, 2, 3, 4}; - vertex_t h_dst[] = {1, 3, 4, 0, 1, 3, 5, 5}; - weight_t h_wgt[] = {0.1f, 2.1f, 1.1f, 5.1f, 3.1f, 4.1f, 7.2f, 3.2f}; - weight_t h_hubs[] = {0.347296, 0.532089, 1, 0.00000959, 0.00000959, 0}; - weight_t h_authorities[] = {0.652704, 0.879385, 0, 1, 0.347296, 0.00002428}; - vertex_t h_initial_vertices[] = { 0, 1, 2, 3, 4 }; - weight_t h_initial_hubs[] = {0.347296, 0.532089, 1, 0.00003608, 0.00003608}; + vertex_t h_src[] = {0, 1, 1, 2, 2, 2, 3, 4}; + vertex_t h_dst[] = {1, 3, 4, 0, 1, 3, 5, 5}; + weight_t h_wgt[] = {0.1f, 2.1f, 1.1f, 5.1f, 3.1f, 4.1f, 7.2f, 3.2f}; + weight_t h_hubs[] = {0.347296, 0.532089, 1, 0.00000959, 0.00000959, 0}; + weight_t h_authorities[] = {0.652704, 0.879385, 0, 1, 0.347296, 0.00002428}; + vertex_t h_initial_vertices[] = {0, 1, 2, 3, 4}; + weight_t h_initial_hubs[] = {0.347296, 0.532089, 1, 0.00003608, 0.00003608}; double epsilon = 0.0001; size_t max_iterations = 20; diff --git a/cpp/tests/c_api/mg_katz_test.c b/cpp/tests/c_api/mg_katz_test.c index c8de4f135ea..ca2de1bb194 100644 --- a/cpp/tests/c_api/mg_katz_test.c +++ b/cpp/tests/c_api/mg_katz_test.c @@ -48,7 +48,7 @@ int generic_katz_test(const cugraph_resource_handle_t* handle, cugraph_type_erased_device_array_view_t* betas_view = NULL; ret_code = create_mg_test_graph( - handle, h_src, h_dst, h_wgt, num_edges, store_transposed, &p_graph, &ret_error); + handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_mg_test_graph failed."); diff --git a/cpp/tests/c_api/mg_pagerank_test.c b/cpp/tests/c_api/mg_pagerank_test.c index e7ead863c4d..7c557d7bed8 100644 --- a/cpp/tests/c_api/mg_pagerank_test.c +++ b/cpp/tests/c_api/mg_pagerank_test.c @@ -46,7 +46,7 @@ int generic_pagerank_test(const cugraph_resource_handle_t* handle, cugraph_centrality_result_t* p_result = NULL; ret_code = create_mg_test_graph( - handle, h_src, h_dst, h_wgt, num_edges, store_transposed, &p_graph, &ret_error); + handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_mg_test_graph failed."); @@ -64,8 +64,10 @@ int generic_pagerank_test(const cugraph_resource_handle_t* handle, vertices = cugraph_centrality_result_get_vertices(p_result); pageranks = cugraph_centrality_result_get_values(p_result); - vertex_t h_vertices[num_vertices]; - weight_t h_pageranks[num_vertices]; + size_t num_local_vertices = cugraph_type_erased_device_array_view_size(vertices); + + vertex_t h_vertices[num_local_vertices]; + weight_t h_pageranks[num_local_vertices]; ret_code = cugraph_type_erased_device_array_view_copy_to_host( handle, (byte_t*)h_vertices, vertices, &ret_error); @@ -75,8 +77,6 @@ int generic_pagerank_test(const cugraph_resource_handle_t* handle, handle, (byte_t*)h_pageranks, pageranks, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); - size_t num_local_vertices = cugraph_type_erased_device_array_view_size(vertices); - for (int i = 0; (i < num_local_vertices) && (test_ret_value == 0); ++i) { TEST_ASSERT(test_ret_value, nearlyEqual(h_result[h_vertices[i]], h_pageranks[i], 0.001), diff --git a/cpp/tests/c_api/mg_strongly_connected_components_test.c b/cpp/tests/c_api/mg_strongly_connected_components_test.c new file mode 100644 index 00000000000..f7659b8023a --- /dev/null +++ b/cpp/tests/c_api/mg_strongly_connected_components_test.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2022, 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 float weight_t; + +int generic_scc_test(const cugraph_resource_handle_t* handle, + vertex_t* h_src, + vertex_t* h_dst, + weight_t* h_wgt, + vertex_t* h_result, + size_t num_vertices, + size_t num_edges, + bool_t store_transposed) +{ + int test_ret_value = 0; + + cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; + cugraph_error_t* ret_error; + + cugraph_graph_t* p_graph = NULL; + cugraph_labeling_result_t* p_result = NULL; + + ret_code = create_mg_test_graph( + handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); + + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_mg_test_graph failed."); + + ret_code = cugraph_strongly_connected_components(handle, p_graph, FALSE, &p_result, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_NOT_IMPLEMENTED, "SCC should not be implemented, but is"); + +#if 0 + // FIXME: Actual implementation will be something like this + TEST_ASSERT( + test_ret_value, ret_code == CUGRAPH_SUCCESS, "cugraph_strongly_connected_components failed."); + + // NOTE: Because we get back vertex ids and components, we can simply compare + // the returned values with the expected results for the entire + // graph. Each GPU will have a subset of the total vertices, so + // they will do a subset of the comparisons. + cugraph_type_erased_device_array_view_t* vertices; + cugraph_type_erased_device_array_view_t* components; + + vertices = cugraph_labeling_result_get_vertices(p_result); + components = cugraph_labeling_result_get_labels(p_result); + + size_t num_local_vertices = cugraph_type_erased_device_array_view_size(vertices); + + vertex_t h_vertices[num_local_vertices]; + vertex_t h_components[num_local_vertices]; + + ret_code = cugraph_type_erased_device_array_view_copy_to_host( + handle, (byte_t*)h_vertices, vertices, &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_components, components, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); + + vertex_t component_check[num_vertices]; + for (vertex_t i = 0; i < num_vertices; ++i) { + component_check[i] = num_vertices; + } + + vertex_t num_errors = 0; + for (vertex_t i = 0; i < num_local_vertices; ++i) { + if (component_check[h_components[i]] == num_vertices) { + component_check[h_components[i]] = h_result[h_vertices[i]]; + } else if (component_check[h_components[i]] != h_result[h_vertices[i]]) { + ++num_errors; + } + } + + TEST_ASSERT(test_ret_value, num_errors == 0, "strongly connected components results don't match"); + + cugraph_type_erased_device_array_view_free(components); + cugraph_type_erased_device_array_view_free(vertices); + cugraph_labeling_result_free(p_result); +#endif + + cugraph_mg_graph_free(p_graph); + cugraph_error_free(ret_error); + + return test_ret_value; +} + +int test_strongly_connected_components(const cugraph_resource_handle_t* handle) +{ + size_t num_edges = 16; + size_t num_vertices = 12; + + vertex_t h_src[] = {0, 1, 1, 2, 2, 2, 3, 4, 6, 7, 7, 8, 8, 8, 9, 10}; + vertex_t h_dst[] = {1, 3, 4, 0, 1, 3, 5, 5, 7, 9, 10, 6, 7, 9, 11, 11}; + weight_t h_wgt[] = { + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + vertex_t h_result[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}; + + // SCC wants store_transposed = FALSE + return generic_scc_test(handle, h_src, h_dst, h_wgt, h_result, num_vertices, num_edges, FALSE); +} + +/******************************************************************************/ + +int main(int argc, char** argv) +{ + // Set up MPI: + int comm_rank; + int comm_size; + int num_gpus_per_node; + cudaError_t status; + int mpi_status; + int result = 0; + cugraph_resource_handle_t* handle = NULL; + cugraph_error_t* ret_error; + cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; + int prows = 1; + + C_MPI_TRY(MPI_Init(&argc, &argv)); + C_MPI_TRY(MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank)); + C_MPI_TRY(MPI_Comm_size(MPI_COMM_WORLD, &comm_size)); + C_CUDA_TRY(cudaGetDeviceCount(&num_gpus_per_node)); + C_CUDA_TRY(cudaSetDevice(comm_rank % num_gpus_per_node)); + + void* raft_handle = create_raft_handle(prows); + handle = cugraph_create_resource_handle(raft_handle); + + if (result == 0) { + result |= RUN_MG_TEST(test_strongly_connected_components, handle); + + cugraph_free_resource_handle(handle); + } + + free_raft_handle(raft_handle); + + C_MPI_TRY(MPI_Finalize()); + + return result; +} diff --git a/cpp/tests/c_api/mg_test_utils.cpp b/cpp/tests/c_api/mg_test_utils.cpp index 9539e73cf18..41bdcefaf3a 100644 --- a/cpp/tests/c_api/mg_test_utils.cpp +++ b/cpp/tests/c_api/mg_test_utils.cpp @@ -103,6 +103,7 @@ extern "C" int create_mg_test_graph(const cugraph_resource_handle_t* handle, float* h_wgt, size_t num_edges, bool_t store_transposed, + bool_t is_symmetric, cugraph_graph_t** p_graph, cugraph_error_t** ret_error) { @@ -110,7 +111,7 @@ extern "C" int create_mg_test_graph(const cugraph_resource_handle_t* handle, cugraph_error_code_t ret_code; cugraph_graph_properties_t properties; - properties.is_symmetric = FALSE; + properties.is_symmetric = is_symmetric; properties.is_multigraph = FALSE; data_type_id_t vertex_tid = INT32; diff --git a/cpp/tests/c_api/mg_test_utils.h b/cpp/tests/c_api/mg_test_utils.h index 0425d8cf74b..827cfa5c885 100644 --- a/cpp/tests/c_api/mg_test_utils.h +++ b/cpp/tests/c_api/mg_test_utils.h @@ -63,5 +63,6 @@ int create_mg_test_graph(const cugraph_resource_handle_t* p_handle, float* h_wgt, size_t num_edges, bool_t store_transposed, + bool_t is_symmetric, cugraph_graph_t** p_graph, cugraph_error_t** ret_error); diff --git a/cpp/tests/c_api/mg_uniform_neighbor_sample_test.c b/cpp/tests/c_api/mg_uniform_neighbor_sample_test.c index 6b867652801..057242d052e 100644 --- a/cpp/tests/c_api/mg_uniform_neighbor_sample_test.c +++ b/cpp/tests/c_api/mg_uniform_neighbor_sample_test.c @@ -54,7 +54,7 @@ int generic_uniform_neighbor_sample_test(const cugraph_resource_handle_t* handle cugraph_type_erased_host_array_view_t* h_fan_out_view = NULL; ret_code = create_mg_test_graph( - handle, h_src, h_dst, h_wgt, num_edges, store_transposed, &graph, &ret_error); + handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "graph creation failed."); ret_code = diff --git a/cpp/tests/c_api/mg_weakly_connected_components_test.c b/cpp/tests/c_api/mg_weakly_connected_components_test.c new file mode 100644 index 00000000000..d0422c8540f --- /dev/null +++ b/cpp/tests/c_api/mg_weakly_connected_components_test.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2022, 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 float weight_t; + +int generic_wcc_test(const cugraph_resource_handle_t* handle, + vertex_t* h_src, + vertex_t* h_dst, + weight_t* h_wgt, + vertex_t* h_result, + size_t num_vertices, + size_t num_edges, + bool_t store_transposed) +{ + int test_ret_value = 0; + + cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; + cugraph_error_t* ret_error; + + cugraph_graph_t* p_graph = NULL; + cugraph_labeling_result_t* p_result = NULL; + + ret_code = create_mg_test_graph( + handle, h_src, h_dst, h_wgt, num_edges, store_transposed, TRUE, &p_graph, &ret_error); + + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_mg_test_graph failed."); + + ret_code = cugraph_weakly_connected_components(handle, p_graph, FALSE, &p_result, &ret_error); + TEST_ASSERT( + test_ret_value, ret_code == CUGRAPH_SUCCESS, "cugraph_weakly_connected_components failed."); + + // NOTE: Because we get back vertex ids and components, we can simply compare + // the returned values with the expected results for the entire + // graph. Each GPU will have a subset of the total vertices, so + // they will do a subset of the comparisons. + cugraph_type_erased_device_array_view_t* vertices; + cugraph_type_erased_device_array_view_t* components; + + vertices = cugraph_labeling_result_get_vertices(p_result); + components = cugraph_labeling_result_get_labels(p_result); + + size_t num_local_vertices = cugraph_type_erased_device_array_view_size(vertices); + + vertex_t h_vertices[num_local_vertices]; + vertex_t h_components[num_local_vertices]; + + ret_code = cugraph_type_erased_device_array_view_copy_to_host( + handle, (byte_t*)h_vertices, vertices, &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_components, components, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); + + vertex_t component_check[num_vertices]; + for (vertex_t i = 0; i < num_vertices; ++i) { + component_check[i] = num_vertices; + } + + vertex_t num_errors = 0; + for (vertex_t i = 0; i < num_local_vertices; ++i) { + if (component_check[h_components[i]] == num_vertices) { + component_check[h_components[i]] = h_result[h_vertices[i]]; + } else if (component_check[h_components[i]] != h_result[h_vertices[i]]) { + ++num_errors; + } + } + + TEST_ASSERT(test_ret_value, num_errors == 0, "weakly connected components results don't match"); + + cugraph_type_erased_device_array_view_free(components); + cugraph_type_erased_device_array_view_free(vertices); + cugraph_labeling_result_free(p_result); + cugraph_mg_graph_free(p_graph); + cugraph_error_free(ret_error); + + return test_ret_value; +} + +int test_weakly_connected_components(const cugraph_resource_handle_t* handle) +{ + size_t num_edges = 32; + size_t num_vertices = 12; + + vertex_t h_src[] = {0, 1, 1, 2, 2, 2, 3, 4, 6, 7, 7, 8, 8, 8, 9, 10, + 1, 3, 4, 0, 1, 3, 5, 5, 7, 9, 10, 6, 7, 9, 11, 11}; + vertex_t h_dst[] = {1, 3, 4, 0, 1, 3, 5, 5, 7, 9, 10, 6, 7, 9, 11, 11, + 0, 1, 1, 2, 2, 2, 3, 4, 6, 7, 7, 8, 8, 8, 9, 10}; + weight_t h_wgt[] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + vertex_t h_result[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}; + + // WCC wants store_transposed = FALSE + return generic_wcc_test(handle, h_src, h_dst, h_wgt, h_result, num_vertices, num_edges, FALSE); +} + +/******************************************************************************/ + +int main(int argc, char** argv) +{ + // Set up MPI: + int comm_rank; + int comm_size; + int num_gpus_per_node; + cudaError_t status; + int mpi_status; + int result = 0; + cugraph_resource_handle_t* handle = NULL; + cugraph_error_t* ret_error; + cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; + int prows = 1; + + C_MPI_TRY(MPI_Init(&argc, &argv)); + C_MPI_TRY(MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank)); + C_MPI_TRY(MPI_Comm_size(MPI_COMM_WORLD, &comm_size)); + C_CUDA_TRY(cudaGetDeviceCount(&num_gpus_per_node)); + C_CUDA_TRY(cudaSetDevice(comm_rank % num_gpus_per_node)); + + void* raft_handle = create_raft_handle(prows); + handle = cugraph_create_resource_handle(raft_handle); + + if (result == 0) { + result |= RUN_MG_TEST(test_weakly_connected_components, handle); + + cugraph_free_resource_handle(handle); + } + + free_raft_handle(raft_handle); + + C_MPI_TRY(MPI_Finalize()); + + return result; +} diff --git a/cpp/tests/c_api/node2vec_test.c b/cpp/tests/c_api/node2vec_test.c index 979e5a7a82b..701d4923fe1 100644 --- a/cpp/tests/c_api/node2vec_test.c +++ b/cpp/tests/c_api/node2vec_test.c @@ -55,7 +55,7 @@ int generic_node2vec_test(vertex_t* h_src, TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "graph creation failed."); ret_code = diff --git a/cpp/tests/c_api/pagerank_test.c b/cpp/tests/c_api/pagerank_test.c index 715692aaa0d..b985fb428e6 100644 --- a/cpp/tests/c_api/pagerank_test.c +++ b/cpp/tests/c_api/pagerank_test.c @@ -49,7 +49,7 @@ int generic_pagerank_test(vertex_t* h_src, TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, FALSE, &p_graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_test_graph failed."); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); diff --git a/cpp/tests/c_api/sssp_test.c b/cpp/tests/c_api/sssp_test.c index f585cdb5fa6..dc9f7a23f47 100644 --- a/cpp/tests/c_api/sssp_test.c +++ b/cpp/tests/c_api/sssp_test.c @@ -52,7 +52,7 @@ int generic_sssp_test(vertex_t* h_src, TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, &p_graph, &ret_error); + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, FALSE, &p_graph, &ret_error); ret_code = cugraph_sssp( p_handle, p_graph, source, cutoff, TRUE, FALSE, &p_result, &ret_error); diff --git a/cpp/tests/c_api/strongly_connected_components_test.c b/cpp/tests/c_api/strongly_connected_components_test.c new file mode 100644 index 00000000000..51e27e4f469 --- /dev/null +++ b/cpp/tests/c_api/strongly_connected_components_test.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2022, 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_test_utils.h" /* RUN_TEST */ + +#include +#include + +#include + +typedef int32_t vertex_t; +typedef int32_t edge_t; +typedef float weight_t; + +int generic_scc_test(vertex_t* h_src, + vertex_t* h_dst, + weight_t* h_wgt, + vertex_t* h_result, + size_t num_vertices, + size_t num_edges, + bool_t store_transposed) +{ + int test_ret_value = 0; + + cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; + cugraph_error_t* ret_error; + + cugraph_resource_handle_t* p_handle = NULL; + cugraph_graph_t* p_graph = NULL; + cugraph_labeling_result_t* p_result = NULL; + + p_handle = cugraph_create_resource_handle(NULL); + TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); + + ret_code = create_test_graph( + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, FALSE, &p_graph, &ret_error); + + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_test_graph failed."); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); + + ret_code = cugraph_strongly_connected_components(p_handle, p_graph, FALSE, &p_result, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_NOT_IMPLEMENTED, "SCC should not be implemented, but is"); + +#if 0 + // FIXME: Actual implementation will be something like this + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); + TEST_ASSERT( + test_ret_value, ret_code == CUGRAPH_SUCCESS, "cugraph_strongly_connected_components failed."); + + cugraph_type_erased_device_array_view_t* vertices; + cugraph_type_erased_device_array_view_t* components; + + vertices = cugraph_labeling_result_get_vertices(p_result); + components = cugraph_labeling_result_get_labels(p_result); + + vertex_t h_vertices[num_vertices]; + vertex_t h_components[num_vertices]; + + ret_code = cugraph_type_erased_device_array_view_copy_to_host( + p_handle, (byte_t*)h_vertices, vertices, &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( + p_handle, (byte_t*)h_components, components, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); + + vertex_t component_check[num_vertices]; + for (vertex_t i = 0; i < num_vertices; ++i) { + component_check[i] = num_vertices; + } + + vertex_t num_errors = 0; + for (vertex_t i = 0; i < num_vertices; ++i) { + if (component_check[h_components[i]] == num_vertices) { + component_check[h_components[i]] = h_result[h_vertices[i]]; + } else if (component_check[h_components[i]] != h_result[h_vertices[i]]) { + ++num_errors; + } + } + + TEST_ASSERT(test_ret_value, num_errors == 0, "strongly connected components results don't match"); + + cugraph_type_erased_device_array_view_free(components); + cugraph_type_erased_device_array_view_free(vertices); + cugraph_labeling_result_free(p_result); +#endif + + cugraph_sg_graph_free(p_graph); + cugraph_free_resource_handle(p_handle); + cugraph_error_free(ret_error); + + return test_ret_value; +} + +int test_strongly_connected_components() +{ + size_t num_edges = 16; + size_t num_vertices = 12; + + vertex_t h_src[] = {0, 1, 1, 2, 2, 2, 3, 4, 6, 7, 7, 8, 8, 8, 9, 10}; + vertex_t h_dst[] = {1, 3, 4, 0, 1, 3, 5, 5, 7, 9, 10, 6, 7, 9, 11, 11}; + weight_t h_wgt[] = { + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + + vertex_t h_result[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}; + + // SCC wants store_transposed = FALSE + return generic_scc_test(h_src, h_dst, h_wgt, h_result, num_vertices, num_edges, FALSE); +} + +/******************************************************************************/ + +int main(int argc, char** argv) +{ + int result = 0; + result |= RUN_TEST(test_strongly_connected_components); + return result; +} diff --git a/cpp/tests/c_api/test_utils.cpp b/cpp/tests/c_api/test_utils.cpp index 4dcc79eed9d..539e6869ec5 100644 --- a/cpp/tests/c_api/test_utils.cpp +++ b/cpp/tests/c_api/test_utils.cpp @@ -36,6 +36,7 @@ extern "C" int create_test_graph(const cugraph_resource_handle_t* p_handle, size_t num_edges, bool_t store_transposed, bool_t renumber, + bool_t is_symmetric, cugraph_graph_t** p_graph, cugraph_error_t** ret_error) { @@ -43,7 +44,7 @@ extern "C" int create_test_graph(const cugraph_resource_handle_t* p_handle, cugraph_error_code_t ret_code; cugraph_graph_properties_t properties; - properties.is_symmetric = FALSE; + properties.is_symmetric = is_symmetric; properties.is_multigraph = FALSE; data_type_id_t vertex_tid = INT32; diff --git a/cpp/tests/c_api/uniform_neighbor_sample_test.c b/cpp/tests/c_api/uniform_neighbor_sample_test.c index b844220677b..d7cbb2e17a8 100644 --- a/cpp/tests/c_api/uniform_neighbor_sample_test.c +++ b/cpp/tests/c_api/uniform_neighbor_sample_test.c @@ -58,7 +58,7 @@ int generic_uniform_neighbor_sample_test(vertex_t* h_src, TEST_ASSERT(test_ret_value, handle != NULL, "resource handle creation failed."); ret_code = create_test_graph( - handle, h_src, h_dst, h_wgt, num_edges, store_transposed, renumber, &graph, &ret_error); + handle, h_src, h_dst, h_wgt, num_edges, store_transposed, renumber, FALSE, &graph, &ret_error); TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "graph creation failed."); ret_code = diff --git a/cpp/tests/c_api/weakly_connected_components_test.c b/cpp/tests/c_api/weakly_connected_components_test.c new file mode 100644 index 00000000000..4f711b4fcde --- /dev/null +++ b/cpp/tests/c_api/weakly_connected_components_test.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2022, 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_test_utils.h" /* RUN_TEST */ + +#include +#include + +#include + +typedef int32_t vertex_t; +typedef int32_t edge_t; +typedef float weight_t; + +int generic_wcc_test(vertex_t* h_src, + vertex_t* h_dst, + weight_t* h_wgt, + vertex_t* h_result, + size_t num_vertices, + size_t num_edges, + bool_t store_transposed) +{ + int test_ret_value = 0; + + cugraph_error_code_t ret_code = CUGRAPH_SUCCESS; + cugraph_error_t* ret_error; + + cugraph_resource_handle_t* p_handle = NULL; + cugraph_graph_t* p_graph = NULL; + cugraph_labeling_result_t* p_result = NULL; + + p_handle = cugraph_create_resource_handle(NULL); + TEST_ASSERT(test_ret_value, p_handle != NULL, "resource handle creation failed."); + + ret_code = create_test_graph( + p_handle, h_src, h_dst, h_wgt, num_edges, store_transposed, FALSE, TRUE, &p_graph, &ret_error); + + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "create_test_graph failed."); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); + + ret_code = cugraph_weakly_connected_components(p_handle, p_graph, FALSE, &p_result, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, cugraph_error_message(ret_error)); + TEST_ASSERT( + test_ret_value, ret_code == CUGRAPH_SUCCESS, "cugraph_weakly_connected_components failed."); + + cugraph_type_erased_device_array_view_t* vertices; + cugraph_type_erased_device_array_view_t* components; + + vertices = cugraph_labeling_result_get_vertices(p_result); + components = cugraph_labeling_result_get_labels(p_result); + + vertex_t h_vertices[num_vertices]; + vertex_t h_components[num_vertices]; + + ret_code = cugraph_type_erased_device_array_view_copy_to_host( + p_handle, (byte_t*)h_vertices, vertices, &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( + p_handle, (byte_t*)h_components, components, &ret_error); + TEST_ASSERT(test_ret_value, ret_code == CUGRAPH_SUCCESS, "copy_to_host failed."); + + vertex_t component_check[num_vertices]; + for (vertex_t i = 0; i < num_vertices; ++i) { + component_check[i] = num_vertices; + } + + vertex_t num_errors = 0; + for (vertex_t i = 0; i < num_vertices; ++i) { + if (component_check[h_components[i]] == num_vertices) { + component_check[h_components[i]] = h_result[h_vertices[i]]; + } else if (component_check[h_components[i]] != h_result[h_vertices[i]]) { + ++num_errors; + } + } + + TEST_ASSERT(test_ret_value, num_errors == 0, "weakly connected components results don't match"); + + cugraph_type_erased_device_array_view_free(components); + cugraph_type_erased_device_array_view_free(vertices); + cugraph_labeling_result_free(p_result); + cugraph_sg_graph_free(p_graph); + cugraph_free_resource_handle(p_handle); + cugraph_error_free(ret_error); + + return test_ret_value; +} + +int test_weakly_connected_components() +{ + size_t num_edges = 32; + size_t num_vertices = 12; + + vertex_t h_src[] = {0, 1, 1, 2, 2, 2, 3, 4, 6, 7, 7, 8, 8, 8, 9, 10, + 1, 3, 4, 0, 1, 3, 5, 5, 7, 9, 10, 6, 7, 9, 11, 11}; + vertex_t h_dst[] = {1, 3, 4, 0, 1, 3, 5, 5, 7, 9, 10, 6, 7, 9, 11, 11, + 0, 1, 1, 2, 2, 2, 3, 4, 6, 7, 7, 8, 8, 8, 9, 10}; + weight_t h_wgt[] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + vertex_t h_result[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}; + + // WCC wants store_transposed = FALSE + return generic_wcc_test(h_src, h_dst, h_wgt, h_result, num_vertices, num_edges, FALSE); +} + +/******************************************************************************/ + +int main(int argc, char** argv) +{ + int result = 0; + result |= RUN_TEST(test_weakly_connected_components); + return result; +} From 7030b830238d93486c1cc36fd4c34f05e3e8b057 Mon Sep 17 00:00:00 2001 From: Vyas Ramasubramani Date: Wed, 13 Apr 2022 09:57:39 -0700 Subject: [PATCH 3/4] Update CMake pinning to allow newer CMake versions. (#2221) CMake 3.23.1 contains the bug fixes that we need to make use of CMake 3.23, so now we can update the pinnings to just avoid 3.23.0. Authors: - Vyas Ramasubramani (https://github.com/vyasr) Approvers: - Jordan Jacobelli (https://github.com/Ethyling) - Robert Maynard (https://github.com/robertmaynard) - Brad Rees (https://github.com/BradReesWork) URL: https://github.com/rapidsai/cugraph/pull/2221 --- conda/environments/cugraph_dev_cuda11.2.yml | 2 +- conda/environments/cugraph_dev_cuda11.4.yml | 2 +- conda/environments/cugraph_dev_cuda11.5.yml | 2 +- conda/recipes/libcugraph/conda_build_config.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/conda/environments/cugraph_dev_cuda11.2.yml b/conda/environments/cugraph_dev_cuda11.2.yml index 01dbc05db12..8bbc224a415 100644 --- a/conda/environments/cugraph_dev_cuda11.2.yml +++ b/conda/environments/cugraph_dev_cuda11.2.yml @@ -25,7 +25,7 @@ dependencies: - networkx>=2.5.1 - clang=11.1.0 - clang-tools=11.1.0 -- cmake>=3.20.1,<3.23 +- cmake>=3.20.1,!=3.23.0 - python>=3.6,<3.9 - notebook>=0.5.0 - boost diff --git a/conda/environments/cugraph_dev_cuda11.4.yml b/conda/environments/cugraph_dev_cuda11.4.yml index d30d5f8cff9..99e42db4973 100644 --- a/conda/environments/cugraph_dev_cuda11.4.yml +++ b/conda/environments/cugraph_dev_cuda11.4.yml @@ -25,7 +25,7 @@ dependencies: - networkx>=2.5.1 - clang=11.1.0 - clang-tools=11.1.0 -- cmake>=3.20.1,<3.23 +- cmake>=3.20.1,!=3.23.0 - python>=3.6,<3.9 - notebook>=0.5.0 - boost diff --git a/conda/environments/cugraph_dev_cuda11.5.yml b/conda/environments/cugraph_dev_cuda11.5.yml index af6c05bf937..dc80bdac95e 100644 --- a/conda/environments/cugraph_dev_cuda11.5.yml +++ b/conda/environments/cugraph_dev_cuda11.5.yml @@ -25,7 +25,7 @@ dependencies: - networkx>=2.5.1 - clang=11.1.0 - clang-tools=11.1.0 -- cmake>=3.20.1,<3.23 +- cmake>=3.20.1,!=3.23.0 - python>=3.6,<3.9 - notebook>=0.5.0 - boost diff --git a/conda/recipes/libcugraph/conda_build_config.yaml b/conda/recipes/libcugraph/conda_build_config.yaml index 63adb7b63cb..203f6f20f7b 100644 --- a/conda/recipes/libcugraph/conda_build_config.yaml +++ b/conda/recipes/libcugraph/conda_build_config.yaml @@ -1,5 +1,5 @@ cmake_version: - - ">=3.20.1,<3.23" + - ">=3.20.1,!=3.23.0" doxygen_version: - ">=1.8.11" From fc7bb31ec2d3ba160a2e7d849e8e017e801a4bdf Mon Sep 17 00:00:00 2001 From: Seunghwa Kang <45857425+seunghwak@users.noreply.github.com> Date: Wed, 13 Apr 2022 19:27:51 -0700 Subject: [PATCH 4/4] Fix typos in documentation (#2225) Fix few typos in documentation. Authors: - Seunghwa Kang (https://github.com/seunghwak) Approvers: - Chuck Hastings (https://github.com/ChuckHastings) URL: https://github.com/rapidsai/cugraph/pull/2225 --- .../cugraph/prims/copy_v_transform_reduce_in_out_nbr.cuh | 4 ++-- .../prims/copy_v_transform_reduce_key_aggregated_out_nbr.cuh | 2 +- .../cugraph/prims/update_frontier_v_push_if_out_nbr.cuh | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/include/cugraph/prims/copy_v_transform_reduce_in_out_nbr.cuh b/cpp/include/cugraph/prims/copy_v_transform_reduce_in_out_nbr.cuh index b8f63e1d8bb..0f944a178e9 100644 --- a/cpp/include/cugraph/prims/copy_v_transform_reduce_in_out_nbr.cuh +++ b/cpp/include/cugraph/prims/copy_v_transform_reduce_in_out_nbr.cuh @@ -914,7 +914,7 @@ void copy_v_transform_reduce_nbr(raft::handle_t const& handle, * value to be reduced. * @param init Initial value to be added to the reduced @p e_op return values for each vertex. * @param vertex_value_output_first Iterator pointing to the vertex property variables for the first - * (inclusive) vertex (assigned to tihs process in multi-GPU). `vertex_value_output_last` + * (inclusive) vertex (assigned to this process in multi-GPU). `vertex_value_output_last` * (exclusive) is deduced as @p vertex_value_output_first + @p * graph_view.local_vertex_partition_range_size(). */ @@ -975,7 +975,7 @@ void copy_v_transform_reduce_in_nbr( * value to be reduced. * @param init Initial value to be added to the reduced @p e_op return values for each vertex. * @param vertex_value_output_first Iterator pointing to the vertex property variables for the - * first (inclusive) vertex (assigned to tihs process in multi-GPU). `vertex_value_output_last` + * first (inclusive) vertex (assigned to this process in multi-GPU). `vertex_value_output_last` * (exclusive) is deduced as @p vertex_value_output_first + @p * graph_view.local_vertex_partition_range_size(). */ diff --git a/cpp/include/cugraph/prims/copy_v_transform_reduce_key_aggregated_out_nbr.cuh b/cpp/include/cugraph/prims/copy_v_transform_reduce_key_aggregated_out_nbr.cuh index 37de44ffe19..ec92081f6b8 100644 --- a/cpp/include/cugraph/prims/copy_v_transform_reduce_key_aggregated_out_nbr.cuh +++ b/cpp/include/cugraph/prims/copy_v_transform_reduce_key_aggregated_out_nbr.cuh @@ -191,7 +191,7 @@ struct reduce_with_init_t { * @param reduce_op Binary operator takes two input arguments and reduce the two variables to one. * @param init Initial value to be added to the reduced @p reduce_op return values for each vertex. * @param vertex_value_output_first Iterator pointing to the vertex property variables for the - * first (inclusive) vertex (assigned to tihs process in multi-GPU). `vertex_value_output_last` + * first (inclusive) vertex (assigned to this process in multi-GPU). `vertex_value_output_last` * (exclusive) is deduced as @p vertex_value_output_first + @p * graph_view.local_vertex_partition_range_size(). */ diff --git a/cpp/include/cugraph/prims/update_frontier_v_push_if_out_nbr.cuh b/cpp/include/cugraph/prims/update_frontier_v_push_if_out_nbr.cuh index fa96c9db3e0..fe2d632a342 100644 --- a/cpp/include/cugraph/prims/update_frontier_v_push_if_out_nbr.cuh +++ b/cpp/include/cugraph/prims/update_frontier_v_push_if_out_nbr.cuh @@ -976,12 +976,12 @@ typename GraphViewType::edge_type compute_num_out_nbrs_from_frontier( * (inclusive) vertex (assigned to this process in multi-GPU). `vertex_value_input_last` (exclusive) * is deduced as @p vertex_value_input_first + @p graph_view.local_vertex_partition_range_size(). * @param vertex_value_output_first Iterator pointing to the vertex property variables for the first - * (inclusive) vertex (assigned to tihs process in multi-GPU). `vertex_value_output_last` + * (inclusive) vertex (assigned to this process in multi-GPU). `vertex_value_output_last` * (exclusive) is deduced as @p vertex_value_output_first + @p * graph_view.local_vertex_partition_range_size(). * @param v_op Ternary operator takes (tagged-)vertex ID, *(@p vertex_value_input_first + i) (where * i is [0, @p graph_view.local_vertex_partition_range_size())) and reduced value of the @p e_op - * outputs for this vertex and returns the target bucket index (for frontier update) and new verrtex + * outputs for this vertex and returns the target bucket index (for frontier update) and new vertex * property values (to update *(@p vertex_value_output_first + i)). The target bucket index should * either be VertexFrontierType::kInvalidBucketIdx or an index in @p next_frontier_bucket_indices. */