Skip to content

Commit

Permalink
Add SG test for MIS and Vertex Coloring
Browse files Browse the repository at this point in the history
  • Loading branch information
Naim committed Mar 12, 2024
1 parent 33e6882 commit fb1c319
Show file tree
Hide file tree
Showing 6 changed files with 512 additions and 10 deletions.
3 changes: 2 additions & 1 deletion cpp/src/components/vertex_coloring_mg.cu
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "coloring_impl.cuh"
#include "vertex_coloring_impl.cuh"

namespace cugraph {

template rmm::device_uvector<int32_t> vertex_coloring(
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/components/vertex_coloring_sg.cu
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "coloring_impl.cuh"
#include "vertex_coloring_impl.cuh"

namespace cugraph {

Expand Down
12 changes: 10 additions & 2 deletions cpp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,14 @@ 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 ------------------------------------------------------------------------------
ConfigureTestMG(MIS_TEST components/mis_test.cu)

###############################################################################################
# - VERTEX COLORING tests -------------------------------------------------------------------
ConfigureTestMG(VERTEX_COLORING_TEST components/vertex_coloring_test.cu)

###################################################################################################
# - SIMILARITY tests ------------------------------------------------------------------------------
ConfigureTest(SIMILARITY_TEST link_prediction/similarity_test.cu)
Expand Down Expand Up @@ -553,8 +561,8 @@ if(BUILD_CUGRAPH_MG_TESTS)
ConfigureTestMG(MG_MIS_TEST components/mg_mis_test.cu)

###############################################################################################
# - MG Graph Coloring tests -------------------------------------------------------------------
ConfigureTestMG(MG_COLORING_TEST components/mg_coloring_test.cu)
# - MG VERTEX COLORING tests -------------------------------------------------------------------
ConfigureTestMG(MG_VERTEX_COLORING_TEST components/mg_vertex_coloring_test.cu)

###############################################################################################
# - MG Core Number tests ----------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ class Tests_MGGraphColoring
{
auto [coloring_usecase, input_usecase] = param;

auto const comm_rank = handle_->get_comms().get_rank();
auto const comm_size = handle_->get_comms().get_size();

HighResTimer hr_timer{};

if (cugraph::test::g_perf) {
Expand Down Expand Up @@ -93,7 +90,7 @@ class Tests_MGGraphColoring

raft::random::RngState rng_state(multi_gpu ? handle_->get_comms().get_rank() : 0);
auto d_colors =
cugraph::coloring<vertex_t, edge_t, multi_gpu>(*handle_, mg_graph_view, rng_state);
cugraph::vertex_coloring<vertex_t, edge_t, multi_gpu>(*handle_, mg_graph_view, rng_state);

// Test Graph Coloring

Expand Down Expand Up @@ -160,7 +157,7 @@ class Tests_MGGraphColoring

RAFT_CUDA_TRY(cudaDeviceSynchronize());

weight_t nr_conflicts = cugraph::transform_reduce_e(
size_t nr_conflicts = cugraph::transform_reduce_e(
*handle_,
mg_graph_view,
multi_gpu ? src_color_cache.view()
Expand All @@ -180,14 +177,16 @@ class Tests_MGGraphColoring
},
vertex_t{0});

ASSERT_TRUE(nr_conflicts == edge_t{0}) << "adjacent vertices can't have same color." << std::endl;

{
thrust::for_each(
thrust::host,
thrust::make_zip_iterator(thrust::make_tuple(
h_colors.begin(), h_vertices_in_this_proces.begin(), h_color_conflicts.begin())),
thrust::make_zip_iterator(thrust::make_tuple(
h_colors.end(), h_vertices_in_this_proces.end(), h_color_conflicts.end())),
[comm_rank](auto color_vetex_and_conflict_flag) {
[](auto color_vetex_and_conflict_flag) {
auto color = thrust::get<0>(color_vetex_and_conflict_flag);
auto v = thrust::get<1>(color_vetex_and_conflict_flag);
auto conflict_flag = thrust::get<2>(color_vetex_and_conflict_flag);
Expand Down
245 changes: 245 additions & 0 deletions cpp/tests/components/mis_test.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
/*
* 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 governin_from_mtxg permissions and
* limitations under the License.
*/

#include "prims/fill_edge_src_dst_property.cuh"
#include "prims/per_v_transform_reduce_incoming_outgoing_e.cuh"
#include "prims/property_generator.cuh"
#include "prims/reduce_op.cuh"
#include "prims/update_edge_src_dst_property.cuh"
#include "utilities/base_fixture.hpp"
#include "utilities/test_graphs.hpp"
#include "utilities/test_utilities.hpp"

#include <cugraph/algorithms.hpp>
#include <cugraph/edge_partition_view.hpp>
#include <cugraph/edge_property.hpp>
#include <cugraph/edge_src_dst_property.hpp>
#include <cugraph/graph_functions.hpp>
#include <cugraph/graph_view.hpp>
#include <cugraph/utilities/dataframe_buffer.hpp>
#include <cugraph/utilities/high_res_timer.hpp>
#include <cugraph/utilities/host_scalar_comm.hpp>

#include <raft/random/rng_state.hpp>

#include <gtest/gtest.h>

#include <chrono>
#include <iostream>
#include <random>

struct MaximalIndependentSet_Usecase {
bool check_correctness{true};
};

template <typename input_usecase_t>
class Tests_SGMaximalIndependentSet
: public ::testing::TestWithParam<std::tuple<MaximalIndependentSet_Usecase, input_usecase_t>> {
public:
Tests_SGMaximalIndependentSet() {}

static void SetUpTestCase() {}
static void TearDownTestCase() {}

virtual void SetUp() {}
virtual void TearDown() {}

template <typename vertex_t, typename edge_t, typename weight_t, typename result_t>
void run_current_test(std::tuple<MaximalIndependentSet_Usecase, input_usecase_t> const& param)
{
auto [mis_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;

auto [sg_graph, sg_edge_weights, sg_renumber_map] =
cugraph::test::construct_graph<vertex_t, edge_t, weight_t, false, multi_gpu>(
handle, input_usecase, false, true);

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;

raft::random::RngState rng_state(0);
auto d_mis = cugraph::maximal_independent_set<vertex_t, edge_t, multi_gpu>(
handle, sg_graph_view, rng_state);

// Test MIS
if (mis_usecase.check_correctness) {
RAFT_CUDA_TRY(cudaDeviceSynchronize());
std::vector<vertex_t> h_mis(d_mis.size());
raft::update_host(h_mis.data(), d_mis.data(), d_mis.size(), handle.get_stream());

RAFT_CUDA_TRY(cudaDeviceSynchronize());

auto vertex_first = sg_graph_view.local_vertex_partition_range_first();
auto vertex_last = sg_graph_view.local_vertex_partition_range_last();

std::for_each(h_mis.begin(), h_mis.end(), [vertex_first, vertex_last](vertex_t v) {
ASSERT_TRUE((v >= vertex_first) && (v < vertex_last));
});

// If a vertex is included in MIS, then none of its neighbor should be

vertex_t local_vtx_partitoin_size = sg_graph_view.local_vertex_partition_range_size();
rmm::device_uvector<vertex_t> d_total_outgoing_nbrs_included_mis(local_vtx_partitoin_size,
handle.get_stream());

rmm::device_uvector<vertex_t> inclusiong_flags(local_vtx_partitoin_size, handle.get_stream());

thrust::uninitialized_fill(
handle.get_thrust_policy(), inclusiong_flags.begin(), inclusiong_flags.end(), vertex_t{0});

thrust::for_each(
handle.get_thrust_policy(),
d_mis.begin(),
d_mis.end(),
[inclusiong_flags =
raft::device_span<vertex_t>(inclusiong_flags.data(), inclusiong_flags.size()),
v_first = sg_graph_view.local_vertex_partition_range_first()] __device__(auto v) {
auto v_offset = v - v_first;
inclusiong_flags[v_offset] = vertex_t{1};
});

RAFT_CUDA_TRY(cudaDeviceSynchronize());

per_v_transform_reduce_outgoing_e(
handle,
sg_graph_view,
cugraph::detail::edge_major_property_view_t<vertex_t, vertex_t const*>(
inclusiong_flags.data()),
cugraph::detail::edge_minor_property_view_t<vertex_t, vertex_t const*>(
inclusiong_flags.data(), vertex_t{0}),
cugraph::edge_dummy_property_t{}.view(),
[] __device__(auto src, auto dst, auto src_included, auto dst_included, auto wt) {
return (src == dst) ? 0 : dst_included;
},
vertex_t{0},
cugraph::reduce_op::plus<vertex_t>{},
d_total_outgoing_nbrs_included_mis.begin());

RAFT_CUDA_TRY(cudaDeviceSynchronize());

std::vector<vertex_t> h_total_outgoing_nbrs_included_mis(
d_total_outgoing_nbrs_included_mis.size());
raft::update_host(h_total_outgoing_nbrs_included_mis.data(),
d_total_outgoing_nbrs_included_mis.data(),
d_total_outgoing_nbrs_included_mis.size(),
handle.get_stream());

RAFT_CUDA_TRY(cudaDeviceSynchronize());

{
auto vertex_first = sg_graph_view.local_vertex_partition_range_first();
auto vertex_last = sg_graph_view.local_vertex_partition_range_last();

std::for_each(h_mis.begin(),
h_mis.end(),
[vertex_first, vertex_last, &h_total_outgoing_nbrs_included_mis](vertex_t v) {
ASSERT_TRUE((v >= vertex_first) && (v < vertex_last))
<< v << " is not within vertex parition range" << std::endl;

ASSERT_TRUE(h_total_outgoing_nbrs_included_mis[v - vertex_first] == 0)
<< v << "'s neighbor is included in MIS" << std::endl;
});
}
}
}
};

using Tests_SGMaximalIndependentSet_File =
Tests_SGMaximalIndependentSet<cugraph::test::File_Usecase>;
using Tests_SGMaximalIndependentSet_Rmat =
Tests_SGMaximalIndependentSet<cugraph::test::Rmat_Usecase>;

TEST_P(Tests_SGMaximalIndependentSet_File, CheckInt32Int32FloatFloat)
{
run_current_test<int32_t, int32_t, float, int>(
override_File_Usecase_with_cmd_line_arguments(GetParam()));
}

TEST_P(Tests_SGMaximalIndependentSet_File, CheckInt32Int64FloatFloat)
{
run_current_test<int32_t, int64_t, float, int>(
override_File_Usecase_with_cmd_line_arguments(GetParam()));
}

TEST_P(Tests_SGMaximalIndependentSet_File, CheckInt64Int64FloatFloat)
{
run_current_test<int64_t, int64_t, float, int>(
override_File_Usecase_with_cmd_line_arguments(GetParam()));
}

TEST_P(Tests_SGMaximalIndependentSet_Rmat, CheckInt32Int32FloatFloat)
{
run_current_test<int32_t, int32_t, float, int>(
override_Rmat_Usecase_with_cmd_line_arguments(GetParam()));
}

TEST_P(Tests_SGMaximalIndependentSet_Rmat, CheckInt32Int64FloatFloat)
{
run_current_test<int32_t, int64_t, float, int>(
override_Rmat_Usecase_with_cmd_line_arguments(GetParam()));
}

TEST_P(Tests_SGMaximalIndependentSet_Rmat, CheckInt64Int64FloatFloat)
{
run_current_test<int64_t, int64_t, float, int>(
override_Rmat_Usecase_with_cmd_line_arguments(GetParam()));
}

bool constexpr check_correctness = false;
INSTANTIATE_TEST_SUITE_P(
file_test,
Tests_SGMaximalIndependentSet_File,
::testing::Combine(::testing::Values(MaximalIndependentSet_Usecase{check_correctness},
MaximalIndependentSet_Usecase{check_correctness}),
::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx"))));

INSTANTIATE_TEST_SUITE_P(
rmat_small_test,
Tests_SGMaximalIndependentSet_Rmat,
::testing::Combine(
::testing::Values(MaximalIndependentSet_Usecase{check_correctness}),
::testing::Values(cugraph::test::Rmat_Usecase(3, 4, 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_SGMaximalIndependentSet_Rmat,
::testing::Combine(
::testing::Values(MaximalIndependentSet_Usecase{check_correctness},
MaximalIndependentSet_Usecase{check_correctness}),
::testing::Values(cugraph::test::Rmat_Usecase(20, 32, 0.57, 0.19, 0.19, 0, false, false))));

CUGRAPH_TEST_PROGRAM_MAIN()
Loading

0 comments on commit fb1c319

Please sign in to comment.