Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ add_library(cugraph_c
src/c_api/sssp.cpp
src/c_api/extract_paths.cpp
src/c_api/random_walks.cpp
src/c_api/triangle_count.cpp
src/c_api/uniform_neighbor_sampling.cpp
src/c_api/labeling_result.cpp
src/c_api/weakly_connected_components.cpp
Expand Down
4 changes: 2 additions & 2 deletions cpp/include/cugraph_c/algorithms.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
#include <cugraph_c/graph.h>
#include <cugraph_c/resource_handle.h>

#include <cugraph_c/centrality_algorithms.h>

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -405,4 +403,6 @@ void cugraph_sample_result_free(cugraph_sample_result_t* result);
}
#endif

#include <cugraph_c/centrality_algorithms.h>
#include <cugraph_c/community_algorithms.h>
#include <cugraph_c/labeling_algorithms.h>
77 changes: 77 additions & 0 deletions cpp/include/cugraph_c/community_algorithms.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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 <cugraph_c/error.h>
#include <cugraph_c/graph.h>
#include <cugraph_c/resource_handle.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Opaque triangle counting result type
*/
typedef struct {
int32_t align_;
} cugraph_triangle_count_result_t;

/**
* @brief Triangle Counting
*
* @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] start Device array of vertices we want to count triangles for. If NULL
* the entire set of vertices in the graph is processed
* @param [in] do_expensive_check
* A flag to run expensive checks for input arguments (if set to true)
* @param [in] result Output from the triangle_count call
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is result labelled in but error is an out? I figured they'd both be out.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Should both be out. I will correct in a follow-up PR.

* @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_triangle_count(const cugraph_resource_handle_t* handle,
cugraph_graph_t* graph,
const cugraph_type_erased_device_array_view_t* start,
bool_t do_expensive_check,
cugraph_triangle_count_result_t** result,
cugraph_error_t** error);

/**
* @brief Get triangle counting vertices
*/
cugraph_type_erased_device_array_view_t* cugraph_triangle_count_result_get_vertices(
cugraph_triangle_count_result_t* result);

/**
* @brief Get triangle counting counts
*/
cugraph_type_erased_device_array_view_t* cugraph_triangle_count_result_get_counts(
cugraph_triangle_count_result_t* result);

/**
* @brief Free a triangle count result
*
* @param [in] result The result from a sampling algorithm
*/
void cugraph_triangle_count_result_free(cugraph_triangle_count_result_t* result);

#ifdef __cplusplus
}
#endif
179 changes: 179 additions & 0 deletions cpp/src/c_api/triangle_count.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/*
* 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 <cugraph_c/algorithms.h>

#include <c_api/abstract_functor.hpp>
#include <c_api/graph.hpp>
#include <c_api/resource_handle.hpp>
#include <c_api/utils.hpp>

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

#include <optional>

namespace cugraph {
namespace c_api {

struct cugraph_triangle_count_result_t {
cugraph_type_erased_device_array_t* vertices_;
cugraph_type_erased_device_array_t* counts_;
};

} // namespace c_api
} // namespace cugraph

namespace {

struct triangle_count_functor : public cugraph::c_api::abstract_functor {
raft::handle_t const& handle_;
cugraph::c_api::cugraph_graph_t* graph_;
cugraph::c_api::cugraph_type_erased_device_array_view_t const* vertices_;
bool do_expensive_check_;
cugraph::c_api::cugraph_triangle_count_result_t* result_{};

triangle_count_functor(::cugraph_resource_handle_t const* handle,
::cugraph_graph_t* graph,
::cugraph_type_erased_device_array_view_t const* vertices,
bool do_expensive_check)
: abstract_functor(),
handle_(*reinterpret_cast<cugraph::c_api::cugraph_resource_handle_t const*>(handle)->handle_),
graph_(reinterpret_cast<cugraph::c_api::cugraph_graph_t*>(graph)),
vertices_(
reinterpret_cast<cugraph::c_api::cugraph_type_erased_device_array_view_t const*>(vertices)),
do_expensive_check_(do_expensive_check)
{
}

template <typename vertex_t,
typename edge_t,
typename weight_t,
bool store_transposed,
bool multi_gpu>
void operator()()
{
if constexpr (!cugraph::is_candidate<vertex_t, edge_t, weight_t>::value) {
unsupported();
} else {
#if 1
error_code_ = CUGRAPH_NOT_IMPLEMENTED;
error_->error_message_ = "Triangle Counting not implemented yet";
#else
// triangle counting expects store_transposed == false
if constexpr (store_transposed) {
error_code_ = cugraph::c_api::
transpose_storage<vertex_t, edge_t, weight_t, store_transposed, multi_gpu>(
handle_, graph_, error_.get());
if (error_code_ != CUGRAPH_SUCCESS) return;
}

auto graph =
reinterpret_cast<cugraph::graph_t<vertex_t, edge_t, weight_t, false, multi_gpu>*>(
graph_->graph_);

auto graph_view = graph->view();

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

rmm::device_uvector<vertex_t> vertices(0, handle_.get_stream());
rmm::device_uvector<edge_t> counts(0, handle_.get_stream());

if (vertices_ != nullptr) {
vertices.resize(vertices_->size_, handle_.get_stream());
counts.resize(vertices_->size_, handle_.get_stream());

raft::copy(
vertices.data(), vertices_->as_type<vertex_t>(), vertices.size(), handle_.get_stream());

cugraph::renumber_ext_vertices<vertex_t, multi_gpu>(
handle_,
vertices.data(),
vertices.size(),
number_map->data(),
graph_view.local_vertex_partition_range_first(),
graph_view.local_vertex_partition_range_last(),
do_expensive_check_);
} else {
counts.resize(graph_view.local_vertex_partition_range_size(), handle_.get_stream());
}

// cugraph::triangle_count<vertex_t, edge_t, weight_t, multi_gpu>(
cugraph::triangle_counts<vertex_t, edge_t, weight_t, multi_gpu>(
handle_,
graph_view,
vertices_ == nullptr
? std::nullopt
: std::make_optional(raft::device_span<vertex_t>{vertices.data(), vertices.size()}),
raft::device_span<edge_t>{counts.data(), counts.size()},
do_expensive_check_);

if (vertices_ == nullptr) {
vertices.resize(graph_view.local_vertex_partition_range_size(), handle_.get_stream());
raft::copy(vertices.data(), number_map->data(), vertices.size(), handle_.get_stream());
}

result_ = new cugraph::c_api::cugraph_triangle_count_result_t{
new cugraph::c_api::cugraph_type_erased_device_array_t(vertices, graph_->vertex_type_),
new cugraph::c_api::cugraph_type_erased_device_array_t(counts, graph_->edge_type_)};
#endif
}
}
};

} // namespace

extern "C" cugraph_type_erased_device_array_view_t* cugraph_triangle_count_result_get_vertices(
cugraph_triangle_count_result_t* result)
{
auto internal_pointer =
reinterpret_cast<cugraph::c_api::cugraph_triangle_count_result_t*>(result);
return reinterpret_cast<cugraph_type_erased_device_array_view_t*>(
internal_pointer->vertices_->view());
}

extern "C" cugraph_type_erased_device_array_view_t* cugraph_triangle_count_result_get_counts(
cugraph_triangle_count_result_t* result)
{
auto internal_pointer =
reinterpret_cast<cugraph::c_api::cugraph_triangle_count_result_t*>(result);
return reinterpret_cast<cugraph_type_erased_device_array_view_t*>(
internal_pointer->counts_->view());
}

extern "C" void cugraph_triangle_count_result_free(cugraph_triangle_count_result_t* result)
{
auto internal_pointer =
reinterpret_cast<cugraph::c_api::cugraph_triangle_count_result_t*>(result);
delete internal_pointer->vertices_;
delete internal_pointer->counts_;
delete internal_pointer;
}

extern "C" cugraph_error_code_t cugraph_triangle_count(
const cugraph_resource_handle_t* handle,
cugraph_graph_t* graph,
const cugraph_type_erased_device_array_view_t* start,
bool_t do_expensive_check,
cugraph_triangle_count_result_t** result,
cugraph_error_t** error)
{
triangle_count_functor functor(handle, graph, start, do_expensive_check);

return cugraph::c_api::run_algorithm(graph, functor, result, error);
}
2 changes: 2 additions & 0 deletions cpp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ if(BUILD_CUGRAPH_MG_TESTS)
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)
ConfigureCTestMG(MG_CAPI_UNIFORM_NEIGHBOR_SAMPLE c_api/mg_uniform_neighbor_sample_test.c c_api/mg_test_utils.cpp)
ConfigureCTestMG(MG_CAPI_TRIANGLE_COUNT c_api/mg_triangle_count_test.c c_api/mg_test_utils.cpp)
else()
message(FATAL_ERROR "OpenMPI NOT found, cannot build MG tests.")
endif()
Expand Down Expand Up @@ -676,6 +677,7 @@ 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)
ConfigureCTest(CAPI_TRIANGLE_COUNT c_api/triangle_count_test.c)

###################################################################################################
### enable testing ################################################################################
Expand Down
6 changes: 6 additions & 0 deletions cpp/tests/c_api/c_test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
} \
}

#define TEST_ALWAYS_ASSERT(STATEMENT, MESSAGE) \
{ \
int tmp = !(STATEMENT); \
if (tmp) { printf("ASSERTION FAILED: %s\n", (MESSAGE)); } \
}

#ifdef __cplusplus
extern "C" {
#endif
Expand Down
Loading