[REVIEW] New Dataset API Clarifying Ownership#1846
Conversation
|
/ok to test 5447a4c |
|
/ok to test 17ab09d |
|
NB: I updated the label to |
@achirkin The problem w/ using mdspan/mdarray for this is that it's not carrying along the proper information to either the algorithms nor the user (which is why we created this specialized class for this in the first place!). Two immediate reasons why this API is necessary:
This new API solves both of these problems while leaving the control over the memory ownership entirely in the user's hands. We've discussed this for a long time. We've known this is needed for a long time. it's time to prioritize this and get it done. I agree that an anstract class might make more sense, but ultimately we should not be moving any owneship over to the algorithm (the user should maintain ownership over the class and underlying memory the entire time). |
|
The doc that outlines some of the API design choices can be found in slack. Let me know if there are any parts of the design that can be altered to better suit our users' needs. The following files are test case files I've added and can be ignored for now. They will be removed before the final merge with upstream repo:
|
|
/ok to test 70b6b58 |
…arch(). Fix MG to use new C API contract and attach padded dataset to standard index prior to search
…ct cuvsDataset, unify storage types extended_storage and merged_storage into one struct cuvsDatasetStorage, and unify dataset layout which is used for deserialize and other functions into one struct cuvsDatasetLayout. Differentiate between types of the same struct with enums.
…ataset to make_extended_storage at both the C++ API layer and the C API layer. This is because merged dataset and extended dataset are not really datasets in the new Dataset API. They are storages composed of multiple components, not just the dataset.
…actual C++ dataset memory allocated. C factories now call C++ API factory implementations and set this addr pointer to point at C++ owning dataset or dataset view. Destructor deletes C++ dataset memory first and then destroys the struct. Split factories by host vs device versions as well as padded vs standard. One flaky rust test test_cagra_serialize_rejects_interior_nul is exposed by this set of changes. The test fails when run with multiple threads but passes when RUST_TEST_THREADS=1 is set.
…struct from owning to view since this requires a whole new struct and is not as simple as the ->as_dataset_view() function at the C++ layer. Also, fixed test case call sites to support new C API design to fix failing cagra ctests
… into separate cuvsCagraBuild***dataset*** overloads taking in DatasetViews. Update python and rust to dispatch on these new build functions. Update C API to first call factory like the user/caller would and then call build with the DatasetView
… any callers and is outdated. The check is done elsewhere inline now.
… which has a build function for each dataset type
…PI which has build functions for each dataset type. Deserialize is hardcoded to outputting standard dataset which needs to be fixed
…t_for_search() on Python API layer. Update python test call sites to use new API contract to attach padded dataset on standard index prior to search. Add dataset_owner to lifetime holder to pass into deserialize as a bridge between C API which only takes layout while C++ API requires a full dataset allocation passed into deserialize()
… which takes in index and out_dataset as inputs passed by reference to be populated. Previously, rust and python deserialize() functions returned index and did not take those 2 parameters as input. Now, we have deserialize() return void and populate index and out_dataset which are passed by reference
…kes in index and out_dataset as inputs passed by reference to be populated. Java API's deserialize() no longer returns index for convenience, it now returns null which mirrors C API
…s failing because the test compared original dataset shape against index.dataset returned from cagra after build which can be padded. This caused a mismatch. The fix was to compare only logical rather than physical padded columns for the dataset equality check.
…r than DLPack. Constrained extend() to only take PaddedDatasetView type as input since extend() internally calls search to add edges for graph and cagra search kernels require padded dataset. Users must allocate and attach a padded dataset through factory call prior to extend() if trying to extend a standard index.
…aph is now never passed in as optional to extend() and graph is now always owned by index. Allocated extended dataset is always passed in by reference to be populated inside extend() but this is just a regular padded or standard dataset. There is no need for the complicated extended_dataset_storage type that bundled dataset and graph together.
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):
New Class Structure (ContainerType Tags + Composition):
Inheritance is removed entirely and all dataset types are on the same level of the inheritance tree.
3 Levels:
Ownership
The index and cagra::build / cagra::index do not own raw vector storage, they only take views.
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
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:
Places where make_padded_dataset/view are called internally (not by user):
Host non-ACE path
Tiered CAGRA
Ownership in Downstream Functions:
Improvements:
Breaking Changes for Dataset API:
The following functions are removed since index no longer owns the dataset, index 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:
Compression Param:
Merge:
These paths have since been removed.
Attach Dataset
Compressed Dataset
Merged Dataset
Deserialize
Helpers
How to attach a compressed dataset onto an uncompressed index?
How to attach a searchable device dataset onto an index built with host build?
a. Utilizes map of host dataset type to device dataset type counterpart
TODOs:
Recent Updates:
Future PRs:
PR#2: Add Support for Compressed Datasets
PR#3: Migrate Rest of Algorithms to use Dataset API