Skip to content

All neighbors C and Python bindings#1282

Merged
rapids-bot[bot] merged 20 commits intorapidsai:branch-25.10from
viclafargue:all-neighbors-python-bindings
Sep 18, 2025
Merged

All neighbors C and Python bindings#1282
rapids-bot[bot] merged 20 commits intorapidsai:branch-25.10from
viclafargue:all-neighbors-python-bindings

Conversation

@viclafargue
Copy link
Copy Markdown
Contributor

Answers #1279

@viclafargue viclafargue added improvement Improves an existing functionality non-breaking Introduces a non-breaking change labels Aug 26, 2025
@jinsolp jinsolp self-requested a review August 27, 2025 16:53
Copy link
Copy Markdown
Contributor

@jinsolp jinsolp left a comment

Choose a reason for hiding this comment

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

Thanks for this PR @viclafargue ! Adding a few comments 🙂

Comment thread python/cuvs/cuvs/tests/test_all_neighbors.py Outdated
Comment thread cpp/include/cuvs/neighbors/all_neighbors.h Outdated
Comment thread python/cuvs/cuvs/common/resources.pyx Outdated
def __dealloc__(self):
check_cuvs(cuvsResourcesDestroy(self.c_obj))

cdef class SNMGResources:
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.

I didn't know we had a separate resource wrapper in cuVS. If there is no explicit reason to not import raft, I think we can just use pylibraft.common.DeviceResourcesSNMG (used like this in cuML).
I think we should be able to have cuvsResources_t to be the arg type in the c api which will dynamically dispatch to the multi gpu if the user passes DeviceResourcesSNMG as the handle.

Copy link
Copy Markdown
Contributor Author

@viclafargue viclafargue Aug 28, 2025

Choose a reason for hiding this comment

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

I removed the cuvsSNMGResources_t type to simplify the API. But, we need the user to be able to instantiate a multi-GPU resource from C. This also enables other bindings. When it comes to handling RAFT handles, this is definitely something we would want to do, but I feel like this may be out of the scope of this PR. Implementing it only in All Neighbors would be inconsistent with the rest of the cuVS Python API. Maybe others would have different insights though. cc @cjnolet

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nitpick- can we please rename deviceSNMG* to DeviceMultiGpu all the way down to the C++ layer? I'm realizing this naming is becoming confusing to users.

Any C/C++ public APIs should absolutely not leak RAFT types. This is actually for more reasons than may be immediately obvious- it turns out the way symbol lookups are resolved in binaries are non-deterministic, and so they can causes nasty segfaults when, say, a symbol is looked up in cugraph or cuml, instantiated, and then later looked up in cuVS (where the instantiated symbol resolves to an uninstantiated one, thus causing a memory illegal access).

I think it's okay to use RAFT types in the Python layer only, so long as the symbol is being exposed through pylibraft's cython/python layer and not being wrapped through cuVS' cython.

Comment thread python/cuvs/cuvs/neighbors/all_neighbors/all_neighbors.pyx Outdated
Comment thread python/cuvs/cuvs/neighbors/all_neighbors/all_neighbors.pyx
@viclafargue viclafargue requested a review from a team as a code owner August 29, 2025 11:03
Comment thread cpp/include/cuvs/core/c_api.h Outdated
Comment thread cpp/include/cuvs/neighbors/all_neighbors.h Outdated
Comment thread cpp/src/core/c_api.cpp Outdated
@@ -0,0 +1,71 @@
All-neighbors
Copy link
Copy Markdown
Member

@cjnolet cjnolet Aug 29, 2025

Choose a reason for hiding this comment

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

I love the docs, but all-neighbros isn't really an index type, it's more-so a way to take a series of dense vectors and construct a knn graph from them (it's really a way to convert dense vectors into a corresponding knn graph when you think about it).
That said, I think this documentation is immensely useful, I'm just proposing we put it in a different spot in the dots (that better reflects its purpose) or rename the "indexes" directory/rst file to be something else- like neighbors.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

What would you like the exact change to be regarding documentation?

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.

I put the cpp doc here so maybe this should go under docs/source/c_api

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

First change I would make is to not put it in the "indexes" docs (`docs/source/indexes/all_neighbors.rst).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The all_neighbors.rst does not document the C API though. In the end, what made the most sense was to rename the indexes directory to neighbors and Nearest Neighbor Indexes to Nearest Neighbor. I also updated the links.

Comment thread python/cuvs/cuvs/common/resources.pyx Outdated
return wrapper


def auto_sync_snmg_resources(f):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The more I think about this, the more I realize we should just be using pylibraft for this instead of wrapping a new type just in cuvs. That would allow cuml and others to benefit from this as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree that it would be neat to allow the use of RAFT handles. But, I think that this would have to be a dedicated follow-up work across the full API. Otherwise, it would need a lot of rework and would make the cuVS API inconsistent.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@viclafargue if you haven't done so already, can you please create an issue for this so it doesn't get lost in the noise of all other things going on?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment thread python/cuvs/cuvs/neighbors/all_neighbors/all_neighbors.pyx Outdated
@cjnolet cjnolet moved this from Todo to In Progress in Unstructured Data Processing Sep 5, 2025
from cuvs.common.exceptions import check_cuvs


cdef class MultiGpuResources:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I haven't checked yet, but do we have a Github issue for this one? Can you please reference it in the TODO here so that we don't lose sight of it? Having a DeviceResources from raft and MultiGpuResources is not consistent and it's ultimately going to affect the user experience. We should make that fix asap (though we don't need to hold up this PR).

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.

I think Victor left an issue here. Please correct me if this isn't the right one @viclafargue

Copy link
Copy Markdown
Contributor Author

@viclafargue viclafargue Sep 17, 2025

Choose a reason for hiding this comment

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

Thanks @jinsolp, an issue has indeed been opened: #1318.

Copy link
Copy Markdown
Contributor

@jinsolp jinsolp left a comment

Choose a reason for hiding this comment

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

Thanks for the work Victor! Left a few comments : )

@@ -0,0 +1,71 @@
All-neighbors
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.

I put the cpp doc here so maybe this should go under docs/source/c_api

Comment thread cpp/src/neighbors/all_neighbors_c.cpp Outdated
Comment thread cpp/include/cuvs/neighbors/all_neighbors.h Outdated
Comment thread cpp/include/cuvs/neighbors/all_neighbors.h Outdated
Comment thread python/cuvs/cuvs/tests/test_all_neighbors.py
Comment on lines +222 to +223
if snmg:
assert recall > 0.85
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.

Do we experience recall drops with snmg?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The recall for multi-GPU IVF-PQ was a bit low. I updated the n_lists parameters for the multi-GPU case. I set a unique threshold at 0.83 to be resilient to minor testing inconsistencies.

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.

Got it. yeah ivfpq seemed to be very sensitive to n_lists.

Copy link
Copy Markdown
Contributor

@jinsolp jinsolp left a comment

Choose a reason for hiding this comment

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

Looking great @viclafargue ! A few final minor comments about the docs 🙂

Comment thread python/cuvs/cuvs/tests/test_all_neighbors.py Outdated
Comment thread docs/source/neighbors/all_neighbors.rst Outdated
Comment thread docs/source/neighbors/all_neighbors.rst Outdated
@viclafargue viclafargue force-pushed the all-neighbors-python-bindings branch from b70ffd4 to 2c22e14 Compare September 18, 2025 12:55
@cjnolet
Copy link
Copy Markdown
Member

cjnolet commented Sep 18, 2025

/merge

@rapids-bot rapids-bot Bot merged commit f33de2a into rapidsai:branch-25.10 Sep 18, 2025
84 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Unstructured Data Processing Sep 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants