Conversation
JunRuiLee
force-pushed
the
feat/ivfpq-l2-range-search
branch
from
September 17, 2026 16:28
89a134c to
907072d
Compare
jerry-024
reviewed
Sep 18, 2026
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.
Summary
Part of #97.
Add IVF-PQ L2 distance-range search to all four Rust reader entry points: single and batch queries, with and without a serialized Roaring allow-list.
DistanceBand,VectorRangeSearchParams,RangeSearchResult, andRangeCollector.Search semantics
Membership is half-open
[lower, upper)in squared-L2 estimated-distance space. Both code widths use floating-point ADC: direct query-to-codebook subvector distances, after optional OPQ and coarse residual subtraction, summed in subquantizer order.The range path does not use u8 FastScan tables, precomputed norm identities, top-K truncation, or original-vector reranking. Membership is independent of list size, batch size, and
optimize_for_search. Range estimates can differ from top-K distances; probing every list removes the IVF coverage gap, not PQ quantization error.Results are uncapped and unordered. Each filter-eligible row is fully evaluated, so PQ
early_abandonedis always zero. Non-finite transformed queries, any coarse distance (including unselected centroids), and consumed PQ estimates fail withInvalidData. Filtered-out and unprobed rows are not evaluated. Query shape, metric, probe width, and serialized filters are validated before empty-band shortcuts. Collector failures propagate without returning partial results or reading subsequent streamed chunks.Performance and memory
Each unique non-empty selected list is read once per call and shared across queries. Large batches use Rayon with query-owned collectors and reusable worker-local scratch. Small workloads remain serial; fully excluded lists/chunks skip distance-table construction.
Non-residual float lookup tables are reused across lists. Residual tables are reused across chunks of the same oversized list and invalidated when the list changes; ordinary residual lists use worker scratch. Query-table caching is lazy and capped at 8 MiB per call, with scratch fallback beyond the cache allowance. This cap covers cached LUTs only, not scratch, inputs, I/O buffers, or uncapped results. The 8 MiB allowance and 8,192 row-query parallel threshold are internal safeguards rather than globally optimal tuning claims.
Local measurements
Apple M2 Pro, macOS/AArch64, Rust 1.95.0, release library and
rustc -Oprobe. The probe uses an in-memory reader, preloaded metadata, warmed thread pools, no row filter, full probing, and an empty-result band[0, 0.0001)to isolate query processing from result materialization. Fixture construction is outside the measurement. Results are median latency over five calls following one warmup, with allocator instrumentation enabled. These synthetic observations are not production-throughput or disk-I/O claims.Allocator-requested bytes for the median-latency sample:
LUT reuse trades bounded live memory for less repeated work; less allocation churn does not imply lower peak memory. These figures measure requested heap bytes, not RSS. The shared result-container memory behavior is outside this PR's scope.
Scope
The change is limited to Rust IVF-PQ L2 range search. Other metrics, language bindings, storage-format changes, top-K scan changes, PQ serialization changes, and shared result-container restructuring are out of scope.
distance.rsand the PQ writer are unchanged. Theio.rschange adds fallible propagation to the streamed-reader callback while retaining its top-K wrapper. No storage migration is required.Tests and validation
Thirteen PQ range integration tests cover both code widths, an independent decoded-code oracle, dense OPQ and residual modes, exact boundaries and adjacent bands, non-finite data, cancellation and overflow, sparse/dense/empty filters, statistics, batch/single and query-permutation equivalence, optimization invariance, and unchanged top-K results. Four focused unit tests cover multi-worker scanning, bounded cached/uncached equivalence and residual invalidation, no table allocation for excluded rows, and parallel collector-error propagation. An index larger than 64 MiB checks bounded streaming, shared physical reads, tail-code layout, cache-budget overflow, and immediate collector-error propagation.
Local validation for this revision on macOS/AArch64 with Rust 1.95.0:
cargo test --offline --locked --workspace: 647 passed, 2 existing ignored.cargo test --offline --locked --release --workspace: 647 passed, 2 existing ignored.cargo fmt --all -- --check: passed.cargo clippy --offline --locked --all-targets --workspace -- -D warnings: passed.python3 tools/check_license_headers.py: passed.git diff --check: passed.Validation caveat: local runs have encountered worker-observation assertion failures in the unchanged IVF-Flat and IVF-SQ tests. The reported full debug/release runs and repository CI pass; historical baseline flakiness has not been established.