Skip to content

Commit aa8ab75

Browse files
authored
Sampling primitive updates to support last-N sampling (#5622)
This PR * refactors sampling primitive functions to minimize code duplication between random sampling and last-N (top-K) sampling * added `per_v_top_k_select_transform_outgoing_e` (in addition to the existing `per_v_random_select_transform_outgoing_e`) to support last-N sampling. `per_v_top_k_select_transform_outgoing_e` selects neighbors with the K highest bias values (bias value should be non-negative and bias 0 neighbors cannot be selected similar to biased random sampling). Authors: - Seunghwa Kang (https://github.com/seunghwak) Approvers: - Chuck Hastings (https://github.com/ChuckHastings) URL: #5622
1 parent 882c286 commit aa8ab75

8 files changed

Lines changed: 2387 additions & 1157 deletions

cpp/include/cugraph/prims/detail/per_v_select_transform_e.cuh

Lines changed: 732 additions & 0 deletions
Large diffs are not rendered by default.

cpp/include/cugraph/prims/detail/sample_and_compute_local_nbr_indices.cuh

Lines changed: 372 additions & 489 deletions
Large diffs are not rendered by default.

cpp/include/cugraph/prims/per_v_random_select_transform_outgoing_e.cuh

Lines changed: 41 additions & 667 deletions
Large diffs are not rendered by default.

cpp/include/cugraph/prims/per_v_top_k_select_transform_outgoing_e.cuh

Lines changed: 275 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
#pragma once
6+
7+
#include <cugraph/export.hpp>
8+
9+
#include <raft/core/device_span.hpp>
10+
#include <raft/core/handle.hpp>
11+
12+
#include <rmm/device_uvector.hpp>
13+
14+
#include <cub/cub.cuh>
15+
16+
#include <cassert>
17+
#include <cstddef>
18+
#include <cstdint>
19+
20+
namespace CUGRAPH_EXPORT cugraph {
21+
namespace detail {
22+
23+
template <typename key_t, typename value_t>
24+
void device_segmented_sort_pairs(raft::handle_t const& handle,
25+
raft::device_span<key_t const> keys_in,
26+
raft::device_span<key_t> keys_out,
27+
raft::device_span<value_t const> values_in,
28+
raft::device_span<value_t> values_out,
29+
raft::device_span<size_t const> begin_offsets,
30+
raft::device_span<size_t const> end_offsets)
31+
{
32+
assert(keys_in.size() == keys_out.size());
33+
assert(values_in.size() == values_out.size());
34+
assert(keys_in.size() == values_in.size());
35+
assert(begin_offsets.size() == end_offsets.size());
36+
37+
size_t tmp_storage_bytes{0};
38+
cub::DeviceSegmentedSort::SortPairs(static_cast<void*>(nullptr),
39+
tmp_storage_bytes,
40+
keys_in.data(),
41+
keys_out.data(),
42+
values_in.data(),
43+
values_out.data(),
44+
keys_in.size(),
45+
begin_offsets.size(),
46+
begin_offsets.data(),
47+
end_offsets.data(),
48+
handle.get_stream());
49+
rmm::device_uvector<std::byte> d_tmp_storage(tmp_storage_bytes, handle.get_stream());
50+
cub::DeviceSegmentedSort::SortPairs(d_tmp_storage.data(),
51+
tmp_storage_bytes,
52+
keys_in.data(),
53+
keys_out.data(),
54+
values_in.data(),
55+
values_out.data(),
56+
keys_in.size(),
57+
begin_offsets.size(),
58+
begin_offsets.data(),
59+
end_offsets.data(),
60+
handle.get_stream());
61+
}
62+
63+
// offsets is a CSR offset array of size num_segments + 1
64+
template <typename key_t, typename value_t>
65+
void device_segmented_sort_pairs(raft::handle_t const& handle,
66+
raft::device_span<key_t const> keys_in,
67+
raft::device_span<key_t> keys_out,
68+
raft::device_span<value_t const> values_in,
69+
raft::device_span<value_t> values_out,
70+
raft::device_span<size_t const> offsets)
71+
{
72+
assert(offsets.size() >= size_t{1});
73+
device_segmented_sort_pairs(
74+
handle,
75+
keys_in,
76+
keys_out,
77+
values_in,
78+
values_out,
79+
raft::device_span<size_t const>{offsets.data(), offsets.size() - 1},
80+
raft::device_span<size_t const>{offsets.data() + 1, offsets.size() - 1});
81+
}
82+
83+
} // namespace detail
84+
} // namespace CUGRAPH_EXPORT cugraph

cpp/tests/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,11 @@ if(BUILD_CUGRAPH_MG_TESTS)
819819
ConfigureTestMG(MG_PER_V_RANDOM_SELECT_TRANSFORM_OUTGOING_E_TEST
820820
prims/mg_per_v_random_select_transform_outgoing_e.cu)
821821

822+
###############################################################################################
823+
# - MG PRIMS PER_V_TOP_K_SELECT_TRANSFORM_OUTGOING_E tests ------------------------------------
824+
ConfigureTestMG(MG_PER_V_TOP_K_SELECT_TRANSFORM_OUTGOING_E_TEST
825+
prims/mg_per_v_top_k_select_transform_outgoing_e.cu)
826+
822827
###############################################################################################
823828
# - MG PRIMS PER_V_PAIR_TRANSFORM_SRC_DST_NBR_INTERSECTION tests ------------------------------
824829
ConfigureTestMG(MG_PER_V_PAIR_TRANSFORM_SRC_DST_NBR_INTERSECTION_TEST

cpp/tests/prims/mg_per_v_random_select_transform_outgoing_e.cu

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION.
2+
* SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

@@ -610,6 +610,7 @@ class Tests_MGPerVRandomSelectTransformOutgoingE
610610

611611
if (sg_nbr_bias_first) {
612612
auto lower_it = thrust::lower_bound(thrust::seq, sg_nbr_first, sg_nbr_last, sg_dst);
613+
if ((lower_it == sg_nbr_last) || (*lower_it != sg_dst)) { return true; }
613614
auto upper_it = thrust::upper_bound(thrust::seq, sg_nbr_first, sg_nbr_last, sg_dst);
614615
bool found = false;
615616
for (auto it = (*sg_nbr_bias_first + cuda::std::distance(sg_nbr_first, lower_it));

0 commit comments

Comments
 (0)