Skip to content

Iterative CAGRA-Q#1810

Open
irina-resh-nvda wants to merge 17 commits into
NVIDIA:mainfrom
irina-resh-nvda:iterative_cagra_q
Open

Iterative CAGRA-Q#1810
irina-resh-nvda wants to merge 17 commits into
NVIDIA:mainfrom
irina-resh-nvda:iterative_cagra_q

Conversation

@irina-resh-nvda

@irina-resh-nvda irina-resh-nvda commented Feb 16, 2026

Copy link
Copy Markdown
Contributor

Iterative cagra graph construction using CAGRA-Q search.

This PR improves the iterative CAGRA build method by enabling PQ compression: the dataset is compressed before the iterative search starts, and CAGRA-Q is used to iteratively update the KNN graph.

@copy-pr-bot

copy-pr-bot Bot commented Feb 16, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

… search

- Configurable growth-phase in-build search params (itopk_size, search_width,
  max_iterations) and internal/smem dtype; itopk auto-forced on the final
  full-size iteration.
- Decouple compression params used during iterative construction from the
  target index compression.
- Add shuffle_dataset option; fix out-of-bounds access from the in-place raft
  gather by switching to an out-of-place gather.
…around)

The shuffle_dataset path used an out-of-place gather into a temporary buffer to
work around an illegal memory access in raft's in-place gather overload when
n_rows * row_len exceeded 2^31 (32-bit index overflow).

That bug is now fixed upstream in raft (NVIDIA/raft#3059, closes #3055), which
the cuvs raft pin now includes. Revert to the in-place gather to drop the extra
full-size temporary allocation and copy.
@irina-resh-nvda
irina-resh-nvda marked this pull request as ready for review July 15, 2026 08:48
@irina-resh-nvda
irina-resh-nvda requested review from a team as code owners July 15, 2026 08:48
@aamijar aamijar changed the title Iterative cagra q Iterative graph build using CAGRA-Q search Jul 22, 2026
@aamijar aamijar changed the title Iterative graph build using CAGRA-Q search Iterative CAGRA-Q Jul 22, 2026
@aamijar

aamijar commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Hi @irina-resh-nvda, thanks for the contribution! I've added some commits to clean up some small things in this PR:

  1. Merge main into this branch and fix merge conflicts 278a4f3
  2. Run pre-commit run --all-files to fix style checker cc65291
  3. There were some unrelated .clangd and .gitignore changes I saw so I reverted that 25e6d7d
  4. There was an unrelated warning change in cuvs_bench so I reverted that 6bca275
  5. The tests/CMakeLists.txt has a duplicate file added so I removed that here 9d44b23
  6. There were some unrelated changes from auto to explicit return type which I reverted 73c9bbc
  7. Two commented out code lines were removed 23cf815

// {std::optional<bool>{std::nullopt}},
// {cuvs::neighbors::MergeStrategy::MERGE_STRATEGY_PHYSICAL,
// cuvs::neighbors::MergeStrategy::MERGE_STRATEGY_LOGICAL});
// inputs.insert(inputs.end(), inputs2.begin(), inputs2.end());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why has this test been commented out?

{16}, // k
{32}, // degree
{ // graph_build_algo::IVF_PQ,
// graph_build_algo::NN_DESCENT,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question: what is the reason for the changes here?

{true},
{false},
{0.995},
{0.01},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why has the recall changed to 1%?

// {std::optional<bool>{std::nullopt}},
// {cuvs::neighbors::MergeStrategy::MERGE_STRATEGY_PHYSICAL,
// cuvs::neighbors::MergeStrategy::MERGE_STRATEGY_LOGICAL});
// inputs.insert(inputs.end(), inputs2.begin(), inputs2.end());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question: why was this commented out?

// Create a dataset with 1000 points
constexpr int64_t n_dataset = 1000;
// Create a dataset with 10000 points
constexpr int64_t n_dataset = 10000;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason this test file has been changed to use n_dataset = 10,000?

dev_ptr,
n_bytes,
cudaMemcpyDeviceToHost,
writeback_stream_));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have a raft function that does this already.

// use memcpy instead of raft::copy to avoid strange behavior with HMM/ATS memory

If there is a problem here, we should try to root fix that in raft.

host_view_.data_handle() + src_row_offset * host_view_.extent(1),
n_bytes,
cudaMemcpyHostToDevice,
prefetch_stream_));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before: let's try to use the raft copy function.

cudaPointerAttributes attr;
RAFT_CUDA_TRY(cudaPointerGetAttributes(&attr, ptr));
return attr.hostPointer != nullptr;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should already have utilities somewhere to do check if a pointer is host or device accessible, either within in raft or cuvs.
I can try to find those functions for you.

* @tparam IdxT The type of the index
*/
template <typename T, typename IdxT>
class batched_device_view_from_host {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use batch_load_iterator for the same purpose?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request New feature or request non-breaking Introduces a non-breaking change

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

5 participants