Skip to content

Commit 9fafec7

Browse files
authored
Merge branch 'branch-25.10' into java/index-close
2 parents ae78c15 + 378440e commit 9fafec7

File tree

10 files changed

+131
-186
lines changed

10 files changed

+131
-186
lines changed

cpp/src/cluster/detail/connectivities.cuh

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021-2024, NVIDIA CORPORATION.
2+
* Copyright (c) 2021-2025, NVIDIA CORPORATION.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
#include <raft/core/resource/cuda_stream.hpp>
2424
#include <raft/core/resource/thrust_policy.hpp>
2525
#include <raft/core/resources.hpp>
26+
#include <raft/linalg/map.cuh>
2627
#include <raft/linalg/unary_op.cuh>
2728
#include <raft/sparse/convert/csr.cuh>
2829
#include <raft/sparse/coo.hpp>
@@ -31,10 +32,6 @@
3132

3233
#include <rmm/device_uvector.hpp>
3334

34-
#include <thrust/iterator/zip_iterator.h>
35-
#include <thrust/transform.h>
36-
#include <thrust/tuple.h>
37-
3835
#include <limits>
3936

4037
namespace cuvs::cluster::agglomerative::detail {
@@ -83,18 +80,25 @@ struct distance_graph_impl<Linkage::KNN_GRAPH, value_idx, value_t> {
8380
data.resize(knn_graph_coo.nnz, stream);
8481

8582
// self-loops get max distance
86-
auto transform_in = thrust::make_zip_iterator(
87-
thrust::make_tuple(knn_graph_coo.rows(), knn_graph_coo.cols(), knn_graph_coo.vals()));
88-
89-
thrust::transform(thrust_policy,
90-
transform_in,
91-
transform_in + knn_graph_coo.nnz,
92-
knn_graph_coo.vals(),
93-
[=] __device__(const thrust::tuple<value_idx, value_idx, value_t>& tup) {
94-
bool self_loop = thrust::get<0>(tup) == thrust::get<1>(tup);
95-
return (self_loop * std::numeric_limits<value_t>::max()) +
96-
(!self_loop * thrust::get<2>(tup));
97-
});
83+
auto rows_view = raft::make_device_vector_view<const value_idx, value_idx>(knn_graph_coo.rows(),
84+
knn_graph_coo.nnz);
85+
auto cols_view = raft::make_device_vector_view<const value_idx, value_idx>(knn_graph_coo.cols(),
86+
knn_graph_coo.nnz);
87+
auto vals_in_view = raft::make_device_vector_view<const value_t, value_idx>(
88+
knn_graph_coo.vals(), knn_graph_coo.nnz);
89+
auto vals_out_view =
90+
raft::make_device_vector_view<value_t, value_idx>(knn_graph_coo.vals(), knn_graph_coo.nnz);
91+
92+
raft::linalg::map(
93+
handle,
94+
vals_out_view,
95+
[=] __device__(const value_idx row, const value_idx col, const value_t val) {
96+
bool self_loop = row == col;
97+
return (self_loop * std::numeric_limits<value_t>::max()) + (!self_loop * val);
98+
},
99+
rows_view,
100+
cols_view,
101+
vals_in_view);
98102

99103
raft::sparse::convert::sorted_coo_to_csr(
100104
knn_graph_coo.rows(), knn_graph_coo.nnz, indptr.data(), m + 1, stream);
@@ -147,7 +151,9 @@ void pairwise_distances(const raft::resources& handle,
147151
value_idx blocks = raft::ceildiv(nnz, (value_idx)256);
148152
fill_indices2<value_idx><<<blocks, 256, 0, stream>>>(indices, m, nnz);
149153

150-
thrust::sequence(exec_policy, indptr, indptr + m, 0, (int)m);
154+
raft::linalg::map_offset(handle,
155+
raft::make_device_vector_view<value_idx, value_idx>(indptr, m),
156+
[=] __device__(value_idx idx) { return idx * m; });
151157

152158
raft::update_device(indptr + m, &nnz, 1, stream);
153159

@@ -160,19 +166,13 @@ void pairwise_distances(const raft::resources& handle,
160166
handle, X_view, X_view, raft::make_device_matrix_view<value_t, value_idx>(data, m, m), metric);
161167

162168
// self-loops get max distance
163-
auto transform_in =
164-
thrust::make_zip_iterator(thrust::make_tuple(thrust::make_counting_iterator(0), data));
165-
166-
thrust::transform(exec_policy,
167-
transform_in,
168-
transform_in + nnz,
169-
data,
170-
[=] __device__(const thrust::tuple<value_idx, value_t>& tup) {
171-
value_idx idx = thrust::get<0>(tup);
172-
bool self_loop = idx % m == idx / m;
173-
return (self_loop * std::numeric_limits<value_t>::max()) +
174-
(!self_loop * thrust::get<1>(tup));
175-
});
169+
auto data_view = raft::make_device_vector_view<value_t, value_idx>(data, nnz);
170+
171+
raft::linalg::map_offset(handle, data_view, [=] __device__(value_idx idx) {
172+
value_t val = data[idx];
173+
bool self_loop = idx % m == idx / m;
174+
return (self_loop * std::numeric_limits<value_t>::max()) + (!self_loop * val);
175+
});
176176
}
177177

178178
/**

cpp/src/neighbors/ball_cover/ball_cover.cuh

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <raft/core/resource/cuda_stream.hpp>
2626
#include <raft/core/resource/thrust_policy.hpp>
2727
#include <raft/core/resources.hpp>
28+
#include <raft/linalg/map.cuh>
2829
#include <raft/matrix/copy.cuh>
2930
#include <raft/random/rng.cuh>
3031
#include <raft/sparse/convert/csr.cuh>
@@ -34,12 +35,9 @@
3435
#include <rmm/exec_policy.hpp>
3536

3637
#include <thrust/fill.h>
37-
#include <thrust/for_each.h>
3838
#include <thrust/functional.h>
39-
#include <thrust/iterator/counting_iterator.h>
4039
#include <thrust/iterator/zip_iterator.h>
4140
#include <thrust/reduce.h>
42-
#include <thrust/sequence.h>
4341
#include <thrust/sort.h>
4442
#include <thrust/tuple.h>
4543

@@ -68,10 +66,7 @@ void sample_landmarks(raft::resources const& handle,
6866
rmm::device_uvector<value_idx> R_indices(index.n_landmarks,
6967
raft::resource::get_cuda_stream(handle));
7068

71-
thrust::sequence(raft::resource::get_thrust_policy(handle),
72-
index.get_R_1nn_cols().data_handle(),
73-
index.get_R_1nn_cols().data_handle() + index.m,
74-
(value_idx)0);
69+
raft::linalg::map_offset(handle, index.get_R_1nn_cols(), raft::identity_op{});
7570

7671
thrust::fill(raft::resource::get_thrust_policy(handle),
7772
R_1nn_ones.data(),
@@ -124,25 +119,23 @@ void construct_landmark_1nn(raft::resources const& handle,
124119
int64_t k,
125120
cuvs::neighbors::ball_cover::index<value_idx, value_t>& index)
126121
{
127-
rmm::device_uvector<value_idx> R_1nn_inds(index.m, raft::resource::get_cuda_stream(handle));
122+
auto R_1nn_inds = raft::make_device_vector<value_idx, value_idx>(handle, index.m);
128123

129124
thrust::fill(raft::resource::get_thrust_policy(handle),
130-
R_1nn_inds.data(),
131-
R_1nn_inds.data() + index.m,
125+
R_1nn_inds.data_handle(),
126+
R_1nn_inds.data_handle() + index.m,
132127
std::numeric_limits<value_idx>::max());
133128

134-
value_idx* R_1nn_inds_ptr = R_1nn_inds.data();
135-
value_t* R_1nn_dists_ptr = index.get_R_1nn_dists().data_handle();
136-
137-
auto idxs = thrust::make_counting_iterator<value_idx>(0);
138-
thrust::for_each(
139-
raft::resource::get_thrust_policy(handle), idxs, idxs + index.m, [=] __device__(value_idx i) {
140-
R_1nn_inds_ptr[i] = R_knn_inds_ptr[i * k];
141-
R_1nn_dists_ptr[i] = R_knn_dists_ptr[i * k];
129+
raft::linalg::map_offset(handle, R_1nn_inds.view(), [R_knn_inds_ptr, k] __device__(value_idx i) {
130+
return R_knn_inds_ptr[i * k];
131+
});
132+
raft::linalg::map_offset(
133+
handle, index.get_R_1nn_dists(), [R_knn_dists_ptr, k] __device__(value_idx i) {
134+
return R_knn_dists_ptr[i * k];
142135
});
143136

144137
auto keys = thrust::make_zip_iterator(
145-
thrust::make_tuple(R_1nn_inds.data(), index.get_R_1nn_dists().data_handle()));
138+
thrust::make_tuple(R_1nn_inds.data_handle(), index.get_R_1nn_dists().data_handle()));
146139

147140
// group neighborhoods for each reference landmark and sort each group by distance
148141
thrust::sort_by_key(raft::resource::get_thrust_policy(handle),
@@ -152,7 +145,7 @@ void construct_landmark_1nn(raft::resources const& handle,
152145
NNComp());
153146

154147
// convert to CSR for fast lookup
155-
raft::sparse::convert::sorted_coo_to_csr(R_1nn_inds.data(),
148+
raft::sparse::convert::sorted_coo_to_csr(R_1nn_inds.data_handle(),
156149
index.m,
157150
index.get_R_indptr().data_handle(),
158151
index.n_landmarks + 1,
@@ -212,18 +205,13 @@ template <typename value_idx, typename value_t>
212205
void compute_landmark_radii(raft::resources const& handle,
213206
cuvs::neighbors::ball_cover::index<value_idx, value_t>& index)
214207
{
215-
auto entries = thrust::make_counting_iterator<value_idx>(0);
216-
217208
const value_idx* R_indptr_ptr = index.get_R_indptr().data_handle();
218209
const value_t* R_1nn_dists_ptr = index.get_R_1nn_dists().data_handle();
219-
value_t* R_radius_ptr = index.get_R_radius().data_handle();
220-
thrust::for_each(raft::resource::get_thrust_policy(handle),
221-
entries,
222-
entries + index.n_landmarks,
223-
[=] __device__(value_idx input) {
224-
value_idx last_row_idx = R_indptr_ptr[input + 1] - 1;
225-
R_radius_ptr[input] = R_1nn_dists_ptr[last_row_idx];
226-
});
210+
raft::linalg::map_offset(
211+
handle, index.get_R_radius(), [R_indptr_ptr, R_1nn_dists_ptr] __device__(value_idx input) {
212+
value_idx last_row_idx = R_indptr_ptr[input + 1] - 1;
213+
return R_1nn_dists_ptr[last_row_idx];
214+
});
227215
}
228216

229217
/**

cpp/src/neighbors/ball_cover/registers.cuh

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <raft/core/resource/cuda_stream.hpp>
2626
#include <raft/core/resource/thrust_policy.hpp>
27+
#include <raft/linalg/unary_op.cuh>
2728
#include <raft/neighbors/detail/faiss_select/key_value_block_select.cuh>
2829
#include <raft/util/cuda_utils.cuh>
2930

@@ -1458,13 +1459,14 @@ void rbc_eps_pass(raft::resources const& handle,
14581459
14591460
if (actual_max > max_k_in) {
14601461
// ceil vd to max_k
1461-
thrust::transform(raft::resource::get_thrust_policy(handle),
1462-
vd_ptr,
1463-
vd_ptr + n_query_rows,
1464-
vd_ptr,
1465-
[max_k_in] __device__(value_idx vd_count) {
1466-
return vd_count > max_k_in ? max_k_in : vd_count;
1467-
});
1462+
raft::linalg::unaryOp(
1463+
vd_ptr,
1464+
vd_ptr,
1465+
n_query_rows,
1466+
[max_k_in] __device__(value_idx vd_count) {
1467+
return vd_count > max_k_in ? max_k_in : vd_count;
1468+
},
1469+
raft::resource::get_cuda_stream(handle));
14681470
}
14691471
14701472
thrust::exclusive_scan(raft::resource::get_thrust_policy(handle),

cpp/src/neighbors/detail/reachability.cuh

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,16 @@
1717
#pragma once
1818
#include "./knn_brute_force.cuh"
1919

20+
#include <raft/core/resource/cuda_stream.hpp>
21+
#include <raft/core/resources.hpp>
22+
#include <raft/linalg/map.cuh>
2023
#include <raft/linalg/unary_op.cuh>
2124
#include <raft/sparse/convert/csr.cuh>
2225
#include <raft/sparse/linalg/symmetrize.cuh>
2326
#include <raft/util/cuda_utils.cuh>
2427
#include <raft/util/cudart_utils.hpp>
2528

2629
#include <rmm/device_uvector.hpp>
27-
#include <rmm/exec_policy.hpp>
28-
29-
#include <thrust/iterator/counting_iterator.h>
30-
#include <thrust/iterator/zip_iterator.h>
31-
#include <thrust/transform.h>
32-
#include <thrust/tuple.h>
3330

3431
namespace cuvs::neighbors::detail::reachability {
3532

@@ -47,17 +44,19 @@ namespace cuvs::neighbors::detail::reachability {
4744
* @param[in] stream stream for which to order cuda operations
4845
*/
4946
template <typename value_idx, typename value_t, int tpb = 256>
50-
void core_distances(
51-
value_t* knn_dists, int min_samples, int n_neighbors, size_t n, value_t* out, cudaStream_t stream)
47+
void core_distances(raft::resources const& handle,
48+
value_t* knn_dists,
49+
int min_samples,
50+
int n_neighbors,
51+
size_t n,
52+
value_t* out)
5253
{
5354
ASSERT(n_neighbors >= min_samples,
5455
"the size of the neighborhood should be greater than or equal to min_samples");
5556

56-
auto exec_policy = rmm::exec_policy(stream);
57-
58-
auto indices = thrust::make_counting_iterator<value_idx>(0);
57+
auto out_view = raft::make_device_vector_view<value_t, value_idx>(out, n);
5958

60-
thrust::transform(exec_policy, indices, indices + n, out, [=] __device__(value_idx row) {
59+
raft::linalg::map_offset(handle, out_view, [=] __device__(value_idx row) {
6160
return knn_dists[row * n_neighbors + (min_samples - 1)];
6261
});
6362
}
@@ -118,7 +117,7 @@ void _compute_core_dists(const raft::resources& handle,
118117
compute_knn(handle, X, inds.data(), dists.data(), m, n, X, m, min_samples, metric);
119118

120119
// Slice core distances (distances to kth nearest neighbor)
121-
core_distances<value_idx>(dists.data(), min_samples, min_samples, m, core_dists, stream);
120+
core_distances<value_idx>(handle, dists.data(), min_samples, min_samples, m, core_dists);
122121
}
123122

124123
// Functor to post-process distances into reachability space
@@ -202,8 +201,7 @@ void mutual_reachability_graph(const raft::resources& handle,
202201
RAFT_EXPECTS(metric == cuvs::distance::DistanceType::L2SqrtExpanded,
203202
"Currently only L2 expanded distance is supported");
204203

205-
auto stream = raft::resource::get_cuda_stream(handle);
206-
auto exec_policy = raft::resource::get_thrust_policy(handle);
204+
auto stream = raft::resource::get_cuda_stream(handle);
207205

208206
rmm::device_uvector<value_idx> coo_rows(min_samples * m, stream);
209207
rmm::device_uvector<value_idx> inds(min_samples * m, stream);
@@ -213,7 +211,7 @@ void mutual_reachability_graph(const raft::resources& handle,
213211
compute_knn(handle, X, inds.data(), dists.data(), m, n, X, m, min_samples, metric);
214212

215213
// Slice core distances (distances to kth nearest neighbor)
216-
core_distances<value_idx>(dists.data(), min_samples, min_samples, m, core_dists, stream);
214+
core_distances<value_idx>(handle, dists.data(), min_samples, min_samples, m, core_dists);
217215

218216
/**
219217
* Compute L2 norm
@@ -222,12 +220,12 @@ void mutual_reachability_graph(const raft::resources& handle,
222220
handle, inds.data(), dists.data(), X, m, n, min_samples, core_dists, (value_t)1.0 / alpha);
223221

224222
// self-loops get max distance
225-
auto coo_rows_counting_itr = thrust::make_counting_iterator<value_idx>(0);
226-
thrust::transform(exec_policy,
227-
coo_rows_counting_itr,
228-
coo_rows_counting_itr + (m * min_samples),
229-
coo_rows.data(),
230-
[min_samples] __device__(value_idx c) -> value_idx { return c / min_samples; });
223+
auto coo_rows_view =
224+
raft::make_device_vector_view<value_idx, value_idx>(coo_rows.data(), m * min_samples);
225+
raft::linalg::map_offset(
226+
handle, coo_rows_view, [min_samples] __device__(value_idx c) -> value_idx {
227+
return c / min_samples;
228+
});
231229

232230
raft::sparse::linalg::symmetrize(handle,
233231
coo_rows.data(),
@@ -241,18 +239,20 @@ void mutual_reachability_graph(const raft::resources& handle,
241239
raft::sparse::convert::sorted_coo_to_csr(out.rows(), out.nnz, indptr, m + 1, stream);
242240

243241
// self-loops get max distance
244-
auto transform_in =
245-
thrust::make_zip_iterator(thrust::make_tuple(out.rows(), out.cols(), out.vals()));
242+
auto rows_view = raft::make_device_vector_view<const value_idx, nnz_t>(out.rows(), out.nnz);
243+
auto cols_view = raft::make_device_vector_view<const value_idx, nnz_t>(out.cols(), out.nnz);
244+
auto vals_in_view = raft::make_device_vector_view<const value_t, nnz_t>(out.vals(), out.nnz);
245+
auto vals_out_view = raft::make_device_vector_view<value_t, nnz_t>(out.vals(), out.nnz);
246246

247-
thrust::transform(exec_policy,
248-
transform_in,
249-
transform_in + out.nnz,
250-
out.vals(),
251-
[=] __device__(const thrust::tuple<value_idx, value_idx, value_t>& tup) {
252-
return thrust::get<0>(tup) == thrust::get<1>(tup)
253-
? std::numeric_limits<value_t>::max()
254-
: thrust::get<2>(tup);
255-
});
247+
raft::linalg::map(
248+
handle,
249+
vals_out_view,
250+
[=] __device__(const value_idx row, const value_idx col, const value_t val) {
251+
return row == col ? std::numeric_limits<value_t>::max() : val;
252+
},
253+
rows_view,
254+
cols_view,
255+
vals_in_view);
256256
}
257257

258258
} // namespace cuvs::neighbors::detail::reachability

cpp/tests/cluster/connect_knn.cu

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <cuvs/distance/distance.hpp>
1818
#include <raft/core/handle.hpp>
19+
#include <raft/linalg/map.cuh>
1920
#include <raft/random/make_blobs.cuh>
2021
#include <raft/sparse/convert/csr.cuh>
2122
#include <raft/sparse/coo.hpp>
@@ -78,7 +79,7 @@ class ConnectKNNTest : public ::testing::TestWithParam<ConnectKNNInputs> {
7879
rmm::device_uvector<T> core_dists(ps.n_rows, stream);
7980
if (ps.mutual_reach) {
8081
cuvs::neighbors::detail::reachability::core_distances<int64_t, T>(
81-
dists.data(), ps.k, ps.k, (size_t)ps.n_rows, core_dists.data(), stream);
82+
handle, dists.data(), ps.k, ps.k, (size_t)ps.n_rows, core_dists.data());
8283

8384
auto epilogue = cuvs::neighbors::detail::reachability::ReachabilityPostProcess<int64_t, T>{
8485
core_dists.data(), 1.0};
@@ -111,13 +112,11 @@ class ConnectKNNTest : public ::testing::TestWithParam<ConnectKNNInputs> {
111112
rmm::device_uvector<int64_t> indptr(ps.n_rows + 1, stream);
112113

113114
// changing inds and dists to sparse format
114-
int64_t k = ps.k;
115-
auto coo_rows_counting_itr = thrust::make_counting_iterator<int64_t>(0);
116-
thrust::transform(raft::resource::get_thrust_policy(handle),
117-
coo_rows_counting_itr,
118-
coo_rows_counting_itr + (ps.n_rows * ps.k),
119-
coo_rows.data(),
120-
[k] __device__(int64_t c) -> int64_t { return c / k; });
115+
int64_t k = ps.k;
116+
auto coo_rows_view =
117+
raft::make_device_vector_view<int64_t, int64_t>(coo_rows.data(), ps.n_rows * ps.k);
118+
raft::linalg::map_offset(
119+
handle, coo_rows_view, [k] __device__(int64_t c) -> int64_t { return c / k; });
121120

122121
raft::sparse::linalg::symmetrize(handle,
123122
coo_rows.data(),

0 commit comments

Comments
 (0)