Skip to content

CAGRA: variable graph degree for CPU-based algorithm - #2031

Open
achirkin wants to merge 44 commits into
NVIDIA:mainfrom
achirkin:fea-variable-graph-degree
Open

CAGRA: variable graph degree for CPU-based algorithm#2031
achirkin wants to merge 44 commits into
NVIDIA:mainfrom
achirkin:fea-variable-graph-degree

Conversation

@achirkin

Copy link
Copy Markdown
Contributor

Modify optimize routine of CAGRA build process to allow variable graph degree.

Introduce variable_graph_degree_fraction parameter (by default = 1.0 = normal / constant degree behavior). This parameter defines the minimum allowed graph degree for any graph node.

@copy-pr-bot

copy-pr-bot Bot commented Apr 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.

@achirkin achirkin self-assigned this Apr 16, 2026
@achirkin achirkin added feature request New feature or request non-breaking Introduces a non-breaking change labels Apr 16, 2026
@achirkin achirkin moved this to In Progress in Unstructured Data Processing Apr 16, 2026
@achirkin

Copy link
Copy Markdown
Contributor Author

/ok to test

@achirkin

Copy link
Copy Markdown
Contributor Author

/ok to test

@achirkin

Copy link
Copy Markdown
Contributor Author

/ok to test

@mfoerste4 mfoerste4 left a comment

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.

graph_core.cuh looks good to me.

Comment thread cpp/src/neighbors/detail/cagra/graph_core.cuh
Comment thread cpp/src/neighbors/detail/cagra/graph_core.cuh
Comment on lines +355 to +364
if constexpr (VariableDegree) {
if (i + 1 == target_pruned_degree) {
// Freeze the detour level after we've placed exactly target_pruned_degree edges.
target_detour_level = warp_min_count;
} else if (i >= target_pruned_degree && warp_min_count > target_detour_level &&
natural_degree == output_graph_degree) {
// The detour level just rose above the target band. Record the natural degree once.
natural_degree = i;
}
}

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.

So we just track the 'natural_degree' here but continue to fill up the output graph - is this required?

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.

Yes, because we need the full graph in the other steps; we only use the natural degree later during the merging step.

@achirkin

Copy link
Copy Markdown
Contributor Author

/ok to test

@achirkin
achirkin changed the base branch from main to release/26.08 July 21, 2026 07:07
@achirkin
achirkin changed the base branch from release/26.08 to main July 29, 2026 16:06
@achirkin
achirkin requested a review from julianmi August 25, 2026 12:25

@julianmi julianmi left a comment

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.

Thanks, this feature looks very promising. Could you add some statistics on the resulting graph degree with the SAME_GRAPH_FOOTPRINT and SIMILAR_SEARCH_PERFORMANCE please? Please also extend the results to include variable_graph_degree_fraction = 0.7 if this becomes the default SIMILAR_SEARCH_PERFORMANCE heuristic.

Comment thread cpp/src/neighbors/detail/cagra/cagra_serialize.cuh Outdated
auto graph_degree = static_cast<int>(index_.graph_degree());
os.write(reinterpret_cast<char*>(&graph_degree), sizeof(int));
int actual_degree = static_cast<int>(index_.graph_degree());
for (int j = 0; j < actual_degree; j++) {

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.

Which values of actual_degree do we see for the two heuristics 0.35 and 0.7? I wonder if it make sense to revert this loop depending of how close the actual and fixed graph degrees are.

Comment thread cpp/src/neighbors/detail/cagra/graph_core.cuh Outdated
Comment thread cpp/src/neighbors/detail/cagra/cagra_serialize.cuh Outdated
Comment thread cpp/include/cuvs/neighbors/cagra.hpp
Comment thread cpp/src/neighbors/detail/cagra/graph_core.cuh
Comment thread cpp/src/neighbors/detail/cagra/graph_core.cuh Outdated
rapids-bot Bot pushed a commit that referenced this pull request Aug 27, 2026
Add the missing HNSW bindings and cleans up the changes in #1719.

Implements feature #2156. More work might be needed to better fit the recall curve provided by HNSW. See #2031. CC @achirkin

Authors:
  - Julian Miller (https://github.com/julianmi)

Approvers:
  - Dante Gama Dessavre (https://github.com/dantegd)
  - Igor Motov (https://github.com/imotov)
  - MithunR (https://github.com/mythrocks)
  - Tamas Bela Feher (https://github.com/tfeher)

URL: #2307
@achirkin

Copy link
Copy Markdown
Contributor Author

Hi @julianmi many thanks for the thorough review! After more benchmarks, I decided to disable the variable degree feature completely for the SIMILAR_SEARCH_PERFORMANCE heuristic. In this mode, the maximum degree is already M and not 2*M, and the heuristics was tailored to show good performance executed in either CAGRA or HNSW, so naturally the best results are observed at fraction = 1.0.
image

@achirkin

Copy link
Copy Markdown
Contributor Author

Typical degree distribution

CAGRA (fraction 0.35)

image

HNSW

image

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