Skip to content

Forward-merge release/26.08 into main - #2383

Open
rapids-bot[bot] wants to merge 4 commits into
mainfrom
release/26.08
Open

Forward-merge release/26.08 into main#2383
rapids-bot[bot] wants to merge 4 commits into
mainfrom
release/26.08

Conversation

@rapids-bot

@rapids-bot rapids-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Forward-merge triggered by push to release/26.08 that creates a PR to keep main up-to-date. If this PR is unable to be immediately merged due to conflicts, it will remain open for the team to manually merge. See forward-merger docs for more info.

### Overview

Addressing #1574 and #1571. 

Replaced strided_dataset with padded_dataset class. Added support all
the way up to CAGRA code.

### Old class structure (Classes + Inheritance):

<img width="973" height="333" alt="Screenshot 2026-06-23 at 7 06 37 PM"
src="https://github.com/user-attachments/assets/470405f1-00ae-4d02-a5f2-aa11612d2c91"
/>

### New Class Structure (ContainerType Tags + Composition):
<img width="2012" height="141" alt="Screenshot 2026-06-23 at 7 07 23 PM"
src="https://github.com/user-attachments/assets/45e3a17f-14e7-4cf4-8d38-eadc2a1c04d3"
/>

Inheritance is removed entirely and all dataset types are on the same
level of the inheritance tree.

3 Levels:
1) Storage
<img width="862" height="442" alt="Screenshot 2026-07-06 at 11 03 41 AM"
src="https://github.com/user-attachments/assets/2f24167f-88a3-4b81-9cd4-ca6ba16d93e4"
/>

2) Container tags
<img width="839" height="250" alt="Screenshot 2026-07-06 at 11 03 11 AM"
src="https://github.com/user-attachments/assets/fcb2bda2-a98b-43ca-946c-fec03ce40aaa"
/>

3) Public dataset/view aliases
<img width="496" height="39" alt="Screenshot 2026-06-23 at 7 02 34 PM"
src="https://github.com/user-attachments/assets/6aaff383-2060-4f4a-bafb-a0f258e81f68"
/>

### Ownership
The index and cagra::build / cagra::index do not own raw vector storage,
they only take views.
- callers (or the C merged holder) must keep backing memory alive for as
long as the index is used.

The old code had a type-erased std::unique_ptr<dataset_view<...>>, i.e.
non-owning view handles. The new code uses templates on the index type
which determines the type of dataset_view the index holds.

### ACE v.s. non-ACE paths on Host

ACE path copies datasets that can't entirely fit in CPU memory in chunks
onto GPU memory by calling make_padded_dataset. This is 1x memory on CPU
and 1x memory on GPU.

### Return types:
Used mainly to maintain lifetime of dataset.

cuvs_cagra_c_api_lifetime_holder
- unique_ptr<vpq_dataset> vpq_owner
- unique_ptr<dataset> padded_dataset_owner
- raft::device_matrix dataset
- cagra::index idx
It is a single C++ struct in cagra.cpp that groups the real cagra::index
with any extra heap-owned things the C API had to create so the index’s
non-owning views stay valid.

### Miscellaneous: Extend Serialize Deserialize
Will fill in later

### Factories:
- make_device_padded_dataset_view
- make_host_padded_dataset_view
- make_device_padded_dataset
- make_host_padded_dataset
- make_vpq_dataset 
    - in pq.hpp and pq.cu
- make_merged_dataset
    - in cagra.hpp

### Places where make_padded_dataset/view are called internally (not by
user):
Host non-ACE path
- cpp/src/neighbors/cagra_build_inst.cu.in
- cagra_from_host_padded in cpp/src/neighbors/iface/iface.hpp
- c/src/neighbors/cagra.cpp

Tiered CAGRA
- update_cagra_ann_dataset_for_stride
- build_upstream_ann

### Ownership in Downstream Functions:

- build() takes dataset_view only.
- Downstream functions search / serialize / deserialize / merge only
take views.

### Improvements:
- build() function previously only supported device dataset inputs. It
now supports host dataset inputs.

### Breaking Changes for Dataset API:
The following functions are removed since index no longer owns the
dataset, index only takes views:
- Removed all owning dataset based builds. Build only takes views.
- Removed all update_dataset() overloads that take owning dataset.
Update_dataset() only takes views.
Removed old functions that took mdspan or derivatives of mdspan.

### 4 cases where index previously owned dataset [all deprecated paths]:

2 edge case build() paths when attach_dataset_on_build == true and a
successful dense attach:
- Non-ACE / typical padded attach: rows live under
index_owning_dataset_storage_ (type-erased owning wrapper, commonly
device_padded_dataset).
- ACE in-memory device_matrix attach: rows live under
index_owning_dataset_storage_ (optional raw device_matrix).

Compression Param:
- implicit vpq dataset creation within build() when compression==True
- this forces index to own new vpq dataset which violates our new
contract that we want index to never own dataset.

Merge:
- MERGE path: merge() internally creates merged_dataset on a deprecated
internal merged dataset creation path. Here, index takes ownership of
merged_dataset by storing it in index_owning_dataset_storage_ .

These paths have since been removed.

### Attach Dataset 
- Previously, in the old code, ACE attach_dataset_on_build called
make_device_padded_dataset on host dataset which did a H2D copy in order
to attach dataset to final index.
- cpp/src/neighbors/detail/cagra/cagra_build.cuh
- This has since been removed. attach_dataset_on_build is disabled for
host build paths. This avoids a H2D copy.

### Compressed Dataset
- Removed old code that did compressed dataset creation within build.
This should only happen in the factory.

### Merged Dataset
- Removed implicit memory allocation within merge(), memory allocation
now delegated to make_merged_dataset() factory. Removed index ownership
within merge.

### Deserialize
- Removed index ownership of dataset during deserialization. Now users
are expected to create/declare the dataset type to be deserialized and
then pass it as a reference to the deserialize() function which will
then populate this dataset and return it to the caller.

### Helpers
- cagra_required_row_width
- matrix_actual_row_width
- matrix_row_width_matches_cagra_required
- convert_dataset_view_to_padded_for_graph_build
- convert_host_to_device_index
- attach_device_dataset_on_host_index

#### How to attach a compressed dataset onto an uncompressed index?
1. construct a new compressed index 
2. copy over the graph and other params from the uncompressed index
3. delete the old uncompressed index
4. attach the vpq dataset onto the compressed index

#### How to attach a searchable device dataset onto an index built with
host build?
1. Convert host index to device index with helper function
convert_host_to_device_index
a. Utilizes map of host dataset type to device dataset type counterpart

### TODOs:
- Bring back Host functions [DONE]
- Mark any old functions that are no longer used as [DONE]
- Use templates wherever possible. Shift towards composition rather than
inheritance [DONE]

### Recent Updates:
- build_ace() and build() functions merged on Public API surface
- removed build_result(), ace_build_result(), and merge_result()
- deprecated internal vpq dataset creation inside build() when
index_params::compression == true --> moved to make_vpq_dataset()
factory
- deprecated internal merged dataset creation inside merge() --> moved
to make_merged_dataset() factory. For backwards compatibility, have
index take ownership of deprecated internal merged dataset creation path
ONLY.
- build() and build_ace() both had a attach_dataset_on_build which
requires ownership of dataset. Ownership is given to index temporarily.
This will later be deprecated. Users will be expected to pass padded
dataset on device and call search() directly. Attach_dataset_on_build
will no longer be supported for host builds.
- added host versions of dataset API
- templated build() and downstream functions to work on host datasets
- added index template type conversion helpers

### Future PRs:
PR#2: Add Support for Compressed Datasets
- pq_dataset
- bbq_dataset
- rabitq_dataset
- sq_dataset 

PR#3: Migrate Rest of Algorithms to use Dataset API
- HNSW
- IVF
- Vamana
- Scann
- Brute Force

---------

Co-authored-by: aamijar <aamijar230@gmail.com>
Co-authored-by: divyegala <divyegala@gmail.com>
Co-authored-by: Yan Zaretskiy <yzaretskiy@nvidia.com>
Co-authored-by: Artem M. Chirkin <9253178+achirkin@users.noreply.github.com>
Co-authored-by: tarangj <jaintarang2015@gmail.com>
Co-authored-by: Tarang Jain <40517122+tarang-jain@users.noreply.github.com>
Co-authored-by: Igor Motov <igor@motovs.org>
@rapids-bot

rapids-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

FAILURE - Unable to forward-merge due to an error, manual merge is necessary. Do not use the Resolve conflicts option in this PR, follow these instructions https://docs.rapids.ai/maintainers/forward-merger/

IMPORTANT: When merging this PR, do not use the auto-merger (i.e. the /merge comment). Instead, an admin must manually merge by changing the merging strategy to Create a Merge Commit. Otherwise, history will be lost and the branches become incompatible.

@rapids-bot
rapids-bot Bot requested a review from gforsyth July 31, 2026 08:44
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.93%. Comparing base (75901ff) to head (2db820e).
⚠️ Report is 32 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2383      +/-   ##
==========================================
+ Coverage   86.70%   86.93%   +0.22%     
==========================================
  Files          33       33              
  Lines         173      176       +3     
==========================================
+ Hits          150      153       +3     
  Misses         23       23              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

cjnolet added 2 commits July 31, 2026 13:13
I resolved a trivial merge conflict in the forward merger from
release/26.08 into main, but it made the commit to merge main into
release/26.08 instead of the other way around. Reverting that merge
commit here.
@cjnolet
cjnolet requested a review from a team as a code owner July 31, 2026 17:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants