Repository navigation
C API: adaptive filtered top-k search by sampled pass rate - #440
Draft
yuejiaointel wants to merge 1 commit into
Draft
yuejiaointel wants to merge 1 commit into
yuejiaointel wants to merge 1 commit into
Conversation
Sample the filter pass rate on every filtered top-k search, also when the filter reports no rate estimate. The early exit for a sampled hit rate below a positive filter_rate() is unchanged. Sampled pass rate p >= 0.5: one plain greedy search per query for max(window, ceil(1.2 * K / p)) neighbors, filtered in distance order. Queries with fewer than K hits are redone with the batch iterator loop. p < 0.5: batch iterator loop as before, with clamp(ceil(0.2 * K / p), 60, 200) extra search buffer slots instead of the default 100 (200 if no sampled id passed). The floor of 60 is the lowest tried that keeps the recall of a window-100 search at 10 % pass rate on a 10k-vector dynamic index (25, 35 and 50 lost recall; 55 and above did not). Add C API tests for the static and the dynamic index.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
filtered_topk_search(C API, static and dynamic Vamana) now picks its search strategy from the filter pass rate it measures on a sample of ids.MIN_SAMPLE_SIZE), also whenfilter_rate()is 0 or not provided. The measured pass rate isp = hits / sampled. The early exit is unchanged: it only applies whenfilter_rate() > 0and the sampled hit rate is below it.p >= 0.5: one plain greedy search per query forN = max(window, ceil(1.2 * K / p))neighbors (search window and capacity bothN). The results are filtered in distance order and the firstKare returned. A query with fewer thanKhits is redone with the batch iterator loop below.p < 0.5: the batch iterator loop as before, but the iterator getsclamp(ceil(0.2 * K / p), 60, 200)extra search buffer slots instead of the default 100 (200 if no sampled id passed). That is 60 slots at 10 % and 200 at 1 % and below (K = 10).The floor of 60 was first 25. A recall test at 1/10 selectivity (10000 vectors, window 100, dynamic index, from #437) lost recall with 25, 35 and 50 extra slots (0.940, 0.935, 0.945 against a 0.95 threshold) and passed with 55 and above, so the floor was raised to 60 (a small test index needed it).
The initial batch size is unchanged (still
max(K, window)when nofilter_rateis given).The greedy searches of a query block run through the index's own
search(one call per block of queries, so it uses the index thread pool); the filtering and the fallback run in the C API thread pool, as the batch loop did before.Why
With a high pass rate almost every candidate passes, so the batch iterator (several
next()calls, a larger search buffer, resumable state) costs more than one ordinary search that is a little wider. With a low pass rate the iterator has to resume several times, and the extra capacity decides how often.Related, independent
Recall at very low selectivity (about 1 % and below) is also limited by the visited set not being reset when the iterator resumes. That is fixed separately in #437 and this PR does not include or depend on it. The tests below were written so they do not depend on it.
Tests
New C API tests (static index and dynamic index, 5000 random vectors, dimension 32, K = 10, native thread pool with 4 threads):
filter_rate() = 0.5with an actual pass rate of 1/20 returns an empty result;filter_rate() = 0.01returns K results.The whole C API test binary (25 test cases) passes locally, built in Release with GCC 11.
Benchmark results to follow.
🤖 Generated with Claude Code