Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable MTMG tests in CI #4923

Open
wants to merge 15 commits into
base: branch-25.04
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
4 changes: 2 additions & 2 deletions conda/recipes/libcugraph/build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# Copyright (c) 2019-2022, NVIDIA CORPORATION.
# Copyright (c) 2019-2025, NVIDIA CORPORATION.

# This assumes the script is executed from the root of the repo directory

Expand All @@ -8,4 +8,4 @@
# openmpi build dependencies). The conda package does NOT include these test
# binaries or extra dependencies, but these are built here for use in CI runs.

./build.sh libcugraph libcugraph_etl cpp-mgtests -n -v --allgpuarch
./build.sh libcugraph libcugraph_etl cpp-mgtests cpp-mtmgtests -n -v --allgpuarch
109 changes: 92 additions & 17 deletions cpp/include/cugraph/mtmg/detail/per_device_edgelist.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023-2024, NVIDIA CORPORATION.
* Copyright (c) 2023-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -51,7 +51,11 @@ namespace detail {
* get_edge_id() and get_edge_type() then the behavior is undefined (data might change
* in some non-deterministic way).
*/
template <typename vertex_t, typename weight_t, typename edge_t, typename edge_type_t>
template <typename vertex_t,
typename weight_t,
typename edge_t,
typename edge_type_t,
typename edge_time_t>
class per_device_edgelist_t {
public:
per_device_edgelist_t() = delete;
Expand All @@ -62,24 +66,30 @@ class per_device_edgelist_t {
/**
* @brief Construct a new per device edgelist t object
*
* @param device_buffer_size Number of edges to store in each device buffer
* @param use_weight Whether or not the edgelist will have weights
* @param use_edge_id Whether or not the edgelist will have edge ids
* @param use_edge_type Whether or not the edgelist will have edge types
* @param stream_view CUDA stream view
* @param device_buffer_size Number of edges to store in each device buffer
* @param use_weight Whether or not the edgelist will have weights
* @param use_edge_id Whether or not the edgelist will have edge ids
* @param use_edge_type Whether or not the edgelist will have edge types
* @param use_edge_start_time Whether or not the edgelist will have edge start times
* @param use_edge_end_time Whether or not the edgelist will have edge end times
* @param stream_view CUDA stream view
*/
per_device_edgelist_t(size_t device_buffer_size,
bool use_weight,
bool use_edge_id,
bool use_edge_type,
bool use_edge_start_time,
bool use_edge_end_time,
rmm::cuda_stream_view stream_view)
: device_buffer_size_{device_buffer_size},
current_pos_{0},
src_{},
dst_{},
wgt_{std::nullopt},
edge_id_{std::nullopt},
edge_type_{std::nullopt}
edge_type_{std::nullopt},
edge_start_time_{std::nullopt},
edge_end_time_{std::nullopt}
{
if (use_weight) { wgt_ = std::make_optional(std::vector<rmm::device_uvector<weight_t>>()); }

Expand All @@ -89,6 +99,14 @@ class per_device_edgelist_t {
edge_type_ = std::make_optional(std::vector<rmm::device_uvector<edge_type_t>>());
}

if (use_edge_start_time) {
edge_start_time_ = std::make_optional(std::vector<rmm::device_uvector<edge_time_t>>());
}

if (use_edge_end_time) {
edge_end_time_ = std::make_optional(std::vector<rmm::device_uvector<edge_time_t>>());
}

create_new_buffers(stream_view);
}

Expand All @@ -104,25 +122,31 @@ class per_device_edgelist_t {
dst_{std::move(other.dst_)},
wgt_{std::move(other.wgt_)},
edge_id_{std::move(other.edge_id_)},
edge_type_{std::move(other.edge_type_)}
edge_type_{std::move(other.edge_type_)},
edge_start_time_{std::move(other.edge_start_time_)},
edge_end_time_{std::move(other.edge_end_time_)}
{
}

/**
* @brief Append a list of edges to the edge list
*
* @param src Source vertex id
* @param dst Destination vertex id
* @param wgt Edge weight
* @param edge_id Edge id
* @param edge_type Edge type
* @param stream_view CUDA stream view
* @param src Source vertex id
* @param dst Destination vertex id
* @param wgt Edge weight
* @param edge_id Edge id
* @param edge_type Edge type
* @param edge_start_time Edge start time
* @param edge_end_time Edge end time
* @param stream_view CUDA stream view
*/
void append(raft::host_span<vertex_t const> src,
raft::host_span<vertex_t const> dst,
std::optional<raft::host_span<weight_t const>> wgt,
std::optional<raft::host_span<edge_t const>> edge_id,
std::optional<raft::host_span<edge_type_t const>> edge_type,
std::optional<raft::host_span<edge_time_t const>> edge_start_time,
std::optional<raft::host_span<edge_time_t const>> edge_end_time,
rmm::cuda_stream_view stream_view)
{
std::vector<std::tuple<size_t, size_t, size_t, size_t>> copy_positions;
Expand Down Expand Up @@ -158,7 +182,11 @@ class per_device_edgelist_t {
&this_edge_id = edge_id_,
&edge_id,
&this_edge_type = edge_type_,
&edge_type](auto tuple) {
&edge_type,
&this_edge_start_time = edge_start_time_,
&edge_start_time,
&this_edge_end_time = edge_end_time_,
&edge_end_time](auto tuple) {
auto [buffer_idx, buffer_pos, input_pos, copy_count] = tuple;

raft::update_device(this_src[buffer_idx].begin() + buffer_pos,
Expand Down Expand Up @@ -188,6 +216,18 @@ class per_device_edgelist_t {
edge_type->begin() + input_pos,
copy_count,
stream_view);

if (this_edge_start_time)
raft::update_device((*this_edge_start_time)[buffer_idx].begin() + buffer_pos,
edge_start_time->begin() + input_pos,
copy_count,
stream_view);

if (this_edge_end_time)
raft::update_device((*this_edge_end_time)[buffer_idx].begin() + buffer_pos,
edge_end_time->begin() + input_pos,
copy_count,
stream_view);
});
}

Expand All @@ -203,6 +243,8 @@ class per_device_edgelist_t {
if (wgt_) wgt_->back().resize(current_pos_, stream_view);
if (edge_id_) edge_id_->back().resize(current_pos_, stream_view);
if (edge_type_) edge_type_->back().resize(current_pos_, stream_view);
if (edge_start_time_) edge_start_time_->back().resize(current_pos_, stream_view);
if (edge_end_time_) edge_end_time_->back().resize(current_pos_, stream_view);
}

bool use_weight() const { return wgt_.has_value(); }
Expand All @@ -211,15 +253,30 @@ class per_device_edgelist_t {

bool use_edge_type() const { return edge_type_.has_value(); }

bool use_edge_start_time() const { return edge_start_time_.has_value(); }

bool use_edge_end_time() const { return edge_end_time_.has_value(); }

std::vector<rmm::device_uvector<vertex_t>>& get_src() { return src_; }
std::vector<rmm::device_uvector<vertex_t>>& get_dst() { return dst_; }
std::optional<std::vector<rmm::device_uvector<weight_t>>>& get_wgt() { return wgt_; }
std::optional<std::vector<rmm::device_uvector<edge_t>>>& get_edge_id() { return edge_id_; }

std::optional<std::vector<rmm::device_uvector<edge_type_t>>>& get_edge_type()
{
return edge_type_;
}

std::optional<std::vector<rmm::device_uvector<edge_type_t>>>& get_edge_start_time()
{
return edge_start_time_;
}

std::optional<std::vector<rmm::device_uvector<edge_type_t>>>& get_edge_end_time()
{
return edge_end_time_;
}

/**
* @brief Consolidate edgelists (if necessary) and shuffle to the proper GPU
*
Expand All @@ -240,30 +297,42 @@ class per_device_edgelist_t {
if (wgt_) resize_and_copy_buffers(*wgt_, total_size, stream);
if (edge_id_) resize_and_copy_buffers(*edge_id_, total_size, stream);
if (edge_type_) resize_and_copy_buffers(*edge_type_, total_size, stream);
if (edge_start_time_) resize_and_copy_buffers(*edge_start_time_, total_size, stream);
if (edge_end_time_) resize_and_copy_buffers(*edge_end_time_, total_size, stream);
}

auto tmp_wgt = wgt_ ? std::make_optional(std::move((*wgt_)[0])) : std::nullopt;
auto tmp_edge_id = edge_id_ ? std::make_optional(std::move((*edge_id_)[0])) : std::nullopt;
auto tmp_edge_type =
edge_type_ ? std::make_optional(std::move((*edge_type_)[0])) : std::nullopt;
auto tmp_edge_start_time =
edge_start_time_ ? std::make_optional(std::move((*edge_start_time_)[0])) : std::nullopt;
auto tmp_edge_end_time =
edge_end_time_ ? std::make_optional(std::move((*edge_end_time_)[0])) : std::nullopt;

std::tie(store_transposed ? dst_[0] : src_[0],
store_transposed ? src_[0] : dst_[0],
tmp_wgt,
tmp_edge_id,
tmp_edge_type,
tmp_edge_start_time,
tmp_edge_end_time,
std::ignore) =
cugraph::detail::shuffle_ext_vertex_pairs_with_values_to_local_gpu_by_edge_partitioning(
handle.raft_handle(),
store_transposed ? std::move(dst_[0]) : std::move(src_[0]),
store_transposed ? std::move(src_[0]) : std::move(dst_[0]),
std::move(tmp_wgt),
std::move(tmp_edge_id),
std::move(tmp_edge_type));
std::move(tmp_edge_type),
std::move(tmp_edge_start_time),
std::move(tmp_edge_end_time));

if (tmp_wgt) ((*wgt_)[0]) = std::move(*tmp_wgt);
if (tmp_edge_id) ((*edge_id_)[0]) = std::move(*tmp_edge_id);
if (tmp_edge_type) ((*edge_type_)[0]) = std::move(*tmp_edge_type);
if (tmp_edge_start_time) ((*edge_start_time_)[0]) = std::move(*tmp_edge_start_time);
if (tmp_edge_end_time) ((*edge_end_time_)[0]) = std::move(*tmp_edge_end_time);
}

private:
Expand Down Expand Up @@ -298,6 +367,10 @@ class per_device_edgelist_t {

if (edge_type_) { edge_type_->emplace_back(device_buffer_size_, stream_view); }

if (edge_start_time_) { edge_start_time_->emplace_back(device_buffer_size_, stream_view); }

if (edge_end_time_) { edge_end_time_->emplace_back(device_buffer_size_, stream_view); }

current_pos_ = 0;
}

Expand All @@ -311,6 +384,8 @@ class per_device_edgelist_t {
std::optional<std::vector<rmm::device_uvector<weight_t>>> wgt_{};
std::optional<std::vector<rmm::device_uvector<edge_t>>> edge_id_{};
std::optional<std::vector<rmm::device_uvector<edge_type_t>>> edge_type_{};
std::optional<std::vector<rmm::device_uvector<edge_time_t>>> edge_start_time_{};
std::optional<std::vector<rmm::device_uvector<edge_time_t>>> edge_end_time_{};
};

} // namespace detail
Expand Down
31 changes: 22 additions & 9 deletions cpp/include/cugraph/mtmg/edgelist.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023-2024, NVIDIA CORPORATION.
* Copyright (c) 2023-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -25,9 +25,14 @@ namespace mtmg {
/**
* @brief Edgelist object for each GPU
*/
template <typename vertex_t, typename weight_t, typename edge_t, typename edge_type_t>
class edgelist_t : public detail::device_shared_wrapper_t<
detail::per_device_edgelist_t<vertex_t, weight_t, edge_t, edge_type_t>> {
template <typename vertex_t,
typename weight_t,
typename edge_t,
typename edge_type_t,
typename edge_time_t>
class edgelist_t
: public detail::device_shared_wrapper_t<
detail::per_device_edgelist_t<vertex_t, weight_t, edge_t, edge_type_t, edge_time_t>> {
public:
/**
* @brief Create a per_device_edgelist for this GPU
Expand All @@ -36,14 +41,22 @@ class edgelist_t : public detail::device_shared_wrapper_t<
size_t device_buffer_size,
bool use_weight,
bool use_edge_id,
bool use_edge_type)
bool use_edge_type,
bool use_edge_start_time,
bool use_edge_end_time)
{
detail::per_device_edgelist_t<vertex_t, weight_t, edge_t, edge_type_t> tmp(
device_buffer_size, use_weight, use_edge_id, use_edge_type, handle.get_stream());
detail::per_device_edgelist_t<vertex_t, weight_t, edge_t, edge_type_t, edge_time_t> tmp(
device_buffer_size,
use_weight,
use_edge_id,
use_edge_type,
use_edge_start_time,
use_edge_end_time,
handle.get_stream());

detail::device_shared_wrapper_t<
detail::per_device_edgelist_t<vertex_t, weight_t, edge_t, edge_type_t>>::set(handle,
std::move(tmp));
detail::per_device_edgelist_t<vertex_t, weight_t, edge_t, edge_type_t, edge_time_t>>::
set(handle, std::move(tmp));
}

/**
Expand Down
Loading
Loading