support ACORN-1 - #673
Conversation
This reverts commit 55c7961.
|
Thanks, @cpegeric! Will be looking into this in a couple of weeks 🤗 |
|
@ashvardanian I found the current fix is buggy and run very slow even in non-filtered search... strange, I already have a check only filtered search with run the new code but not expected. Anyway, just for your reference. Let's see I will have time to revisit the code. thanks. |
…um-cloud#672) Rewrites search_to_find_in_base_ so the 2-hop "bridge" expansion is used where it helps and avoided where it hurts, fixing the prior implementation's slowness and its recall/correctness problems. The 2-hop bridge (visit a filtered-out member's neighbors so the filter-passing subgraph stays connected) is a large win for SELECTIVE filters — on a 50k/64-d set it matches the exhaustive baseline's recall at ~13-15x the QPS — but it is pure M^2 overhead for PERMISSIVE filters, where a plain traverse-through-all is both faster and higher recall. The old code ran the bridge unconditionally, so it was slow at permissive filters and, on a very selective filter (e.g. a predicate matching a single key), could not reach the isolated passing member at all and returned nothing. This version: - Estimates the filter pass-rate from the entry point's base-layer neighborhood (a graph-LOCAL sample near the query, not a uniform global one) and dispatches: permissive/unfiltered -> plain HNSW base expansion; selective -> ACORN (filter members first, only passing ones enter the frontier, then one extra hop through the 1-hop neighbors). - Falls back once to an exhaustive baseline walk when an ACORN pass returns fewer than `wanted` (k) results, so pathologically selective / isolated passing sets are never silently dropped. Gated on `wanted` rather than `expansion`, since a selective filter legitimately has fewer than `ef` passing members and gating on `ef` would fall back on every query and erase the speedup at large `ef`. - Collapses the duplicated dummy/ACORN branches into one loop; threads `wanted` into search_to_find_in_base_ for the fallback gate. Validated: full cpp/test.cpp suite passes (incl. test_filtered_search), single-key predicates return the matching member, and recall/QPS hold across 1%/10%/50% filter selectivities (selective uses ACORN, permissive falls back to baseline). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Reworked the ACORN-1 implementation in Problems with the always-on 2-hop bridgeThe 2-hop bridge (visit a filtered-out member's neighbors so the filter-passing subgraph stays connected) is a big win for selective filters, but running it unconditionally caused two problems:
What changed
Results50k vectors, dim 64, recall@10 vs exact filtered top-k:
So: ~13–15× faster than baseline at matched recall for selective filters, automatic fallback to baseline for permissive ones, and correct for pathologically selective filters. ValidationFull |
Support ACORN-1 by visiting 2-hop-neighbors.
This is the first time to modify the C++ usearch code. This is just the proposal of ACORN-1. Please consider this change and amend whatever you feel appropriate.