From 3e04a0a0132a5f87c0b808e4cbad8019b8ef5c9f Mon Sep 17 00:00:00 2001 From: Irina Reshodko Date: Fri, 20 Feb 2026 07:06:34 -0800 Subject: [PATCH 1/4] added reproducing test --- cpp/tests/CMakeLists.txt | 1 + .../ann_cagra/bug_iterative_cagra_build.cu | 84 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 9fc620b4cb..003dc383b2 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -156,6 +156,7 @@ ConfigureTest( ConfigureTest( NAME NEIGHBORS_ANN_CAGRA_TEST_BUGS PATH neighbors/ann_cagra/bug_extreme_inputs_oob.cu neighbors/ann_cagra/bug_multi_cta_crash.cu + neighbors/ann_cagra/bug_iterative_cagra_build.cu GPUS 1 PERCENT 100 ) diff --git a/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu b/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu new file mode 100644 index 0000000000..4336b696e6 --- /dev/null +++ b/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu @@ -0,0 +1,84 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +#include +#include +#include + +#include +#include + +namespace cuvs::neighbors::cagra { + +template +class CagraIterativeBuildBugTest : public ::testing::Test { + public: + using data_type = DataT; + + protected: + void run() + { + // Set up iterative CAGRA graph building + cagra::index_params index_params; + index_params.graph_degree = 16; + index_params.intermediate_graph_degree = 16; + + // Use iterative CAGRA search for graph building + index_params.graph_build_params = graph_build_params::iterative_search_params(); + + // Build the index + auto cagra_index = + cagra::build(res, index_params, raft::make_const_mdspan(dataset->view())); + raft::resource::sync_stream(res); + + // Verify the index was built successfully + ASSERT_GT(cagra_index.size(), 0); + ASSERT_EQ(cagra_index.dim(), n_dim); + } + + void SetUp() override + { + dataset.emplace(raft::make_device_matrix(res, n_samples, n_dim)); + raft::random::RngState r(1234ULL); + + // Generate random data based on type + if constexpr (std::is_same_v) { + raft::random::normal( + res, r, dataset->data_handle(), n_samples * n_dim, data_type(0), data_type(1)); + } else if constexpr (std::is_same_v) { + raft::random::uniformInt( + res, r, dataset->data_handle(), n_samples * n_dim, int8_t(-128), int8_t(127)); + } else if constexpr (std::is_same_v) { + raft::random::uniformInt( + res, r, dataset->data_handle(), n_samples * n_dim, uint8_t(0), uint8_t(255)); + } + raft::resource::sync_stream(res); + } + + void TearDown() override + { + dataset.reset(); + raft::resource::sync_stream(res); + } + + private: + raft::resources res; + std::optional> dataset = std::nullopt; + + constexpr static int64_t n_samples = 10000; + constexpr static int64_t n_dim = 1024; +}; + +// Instantiate test for different data types +using TestTypes = ::testing::Types; +TYPED_TEST_SUITE(CagraIterativeBuildBugTest, TestTypes); + +TYPED_TEST(CagraIterativeBuildBugTest, IterativeBuildTest) { this->run(); } + +} // namespace cuvs::neighbors::cagra From aabe3fbd469a5b166a9472f1427e2c25b7ddcf80 Mon Sep 17 00:00:00 2001 From: Irina Reshodko Date: Mon, 23 Feb 2026 03:48:12 -0800 Subject: [PATCH 2/4] cudaErrorIllegalAddress fix --- cpp/src/neighbors/detail/cagra/cagra_build.cuh | 2 +- .../neighbors/ann_cagra/bug_iterative_cagra_build.cu | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cpp/src/neighbors/detail/cagra/cagra_build.cuh b/cpp/src/neighbors/detail/cagra/cagra_build.cuh index 97d7bb1bac..a79e12bc74 100644 --- a/cpp/src/neighbors/detail/cagra/cagra_build.cuh +++ b/cpp/src/neighbors/detail/cagra/cagra_build.cuh @@ -2021,7 +2021,7 @@ auto iterative_build_graph( // Allocate memory for search results. constexpr uint64_t max_chunk_size = 8192; - auto topk = intermediate_degree; + auto topk = intermediate_degree + 1; auto dev_neighbors = raft::make_device_matrix(res, max_chunk_size, topk); auto dev_distances = raft::make_device_matrix(res, max_chunk_size, topk); diff --git a/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu b/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu index 4336b696e6..d5281d0cc1 100644 --- a/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu +++ b/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION. * SPDX-License-Identifier: Apache-2.0 */ @@ -28,13 +28,12 @@ class CagraIterativeBuildBugTest : public ::testing::Test { cagra::index_params index_params; index_params.graph_degree = 16; index_params.intermediate_graph_degree = 16; - + // Use iterative CAGRA search for graph building index_params.graph_build_params = graph_build_params::iterative_search_params(); // Build the index - auto cagra_index = - cagra::build(res, index_params, raft::make_const_mdspan(dataset->view())); + auto cagra_index = cagra::build(res, index_params, raft::make_const_mdspan(dataset->view())); raft::resource::sync_stream(res); // Verify the index was built successfully @@ -46,7 +45,7 @@ class CagraIterativeBuildBugTest : public ::testing::Test { { dataset.emplace(raft::make_device_matrix(res, n_samples, n_dim)); raft::random::RngState r(1234ULL); - + // Generate random data based on type if constexpr (std::is_same_v) { raft::random::normal( From d230bfc3c782fced730cb58d7f5073f152cc64b9 Mon Sep 17 00:00:00 2001 From: Irina Reshodko Date: Mon, 23 Feb 2026 04:16:53 -0800 Subject: [PATCH 3/4] style fix --- cpp/tests/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index fd79f572e7..35794adf9b 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -155,7 +155,8 @@ ConfigureTest( ConfigureTest( NAME NEIGHBORS_ANN_CAGRA_TEST_BUGS - PATH neighbors/ann_cagra/bug_extreme_inputs_oob.cu neighbors/ann_cagra/bug_multi_cta_crash.cu + PATH neighbors/ann_cagra/bug_extreme_inputs_oob.cu + neighbors/ann_cagra/bug_multi_cta_crash.cu neighbors/ann_cagra/bug_iterative_cagra_build.cu neighbors/ann_cagra/bug_issue_93_reproducer.cu GPUS 1 From 31f5e9389da8f6450c3f506a2a65c85034ff03a9 Mon Sep 17 00:00:00 2001 From: Irina Reshodko Date: Tue, 24 Feb 2026 00:43:52 -0800 Subject: [PATCH 4/4] addressed suggestions --- cpp/src/neighbors/detail/cagra/cagra_build.cuh | 4 +++- cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/src/neighbors/detail/cagra/cagra_build.cuh b/cpp/src/neighbors/detail/cagra/cagra_build.cuh index a79e12bc74..7a4c70be89 100644 --- a/cpp/src/neighbors/detail/cagra/cagra_build.cuh +++ b/cpp/src/neighbors/detail/cagra/cagra_build.cuh @@ -2021,7 +2021,9 @@ auto iterative_build_graph( // Allocate memory for search results. constexpr uint64_t max_chunk_size = 8192; - auto topk = intermediate_degree + 1; + // +1 because the search may return the query node itself as a neighbor; + // this is consistent with the per-iteration curr_topk = next_graph_degree + 1 + auto topk = intermediate_degree + 1; auto dev_neighbors = raft::make_device_matrix(res, max_chunk_size, topk); auto dev_distances = raft::make_device_matrix(res, max_chunk_size, topk); diff --git a/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu b/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu index d5281d0cc1..aaee5a77e5 100644 --- a/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu +++ b/cpp/tests/neighbors/ann_cagra/bug_iterative_cagra_build.cu @@ -26,6 +26,8 @@ class CagraIterativeBuildBugTest : public ::testing::Test { { // Set up iterative CAGRA graph building cagra::index_params index_params; + // The bug manifests when graph_degree is equal to intermediate_graph_degree + // see issue https://github.com/rapidsai/cuvs/issues/1818 index_params.graph_degree = 16; index_params.intermediate_graph_degree = 16;