perf(symqg): filter neighbors with batch threshold masks - #97
Merged
Conversation
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.
Problem and change
SymphonyQG currently performs a scalar threshold check for every scored neighbor. Build a 32-lane threshold mask after FastScan and iterate only eligible lanes, reducing scalar handling of rejected candidates. Preserve lane order, equal-distance handling, visited checks, and the live threshold recheck as insertions tighten the beam.
Construction can supply partially filled neighborhoods even though finalized rows have a multiple-of-32 degree. Clear mask bits beyond the logical degree so stale IDs in unused physical lanes cannot enter the beam. Keep the fixed-length mask-generation loop for vectorization and avoid shifting a 32-bit value by 32.
This PR changes only
qg.hpp; it does not include the local experiment or test files.Validation
RABITQ_ENABLE_NATIVE_OPTIMIZATION=OFF) andctest: 62/62 passed. Runtime dispatch used AVX-512 on this machine; AVX2 execution was not separately tested../scripts/check-format.sh,./scripts/check-python.sh,git diff --check, and focused clang-tidy for the QG test translation unit passed. Full pre-merge clang-tidy has not been run.tzcnt/blsrenumeration; the tail guard clears high mask bits withbzhi.Earlier measurements of the threshold-mask optimization on GIST1M (960 dimensions, degree 32, squared L2, k=10, one thread pinned to CPU 0 on Xeon Gold 6418H, GCC 14.3,
-O3 -march=native, AVX-512 dispatch) showed raw QPS improvements of 3.9%/5.1%/4.2% at ef 155/180/290 and 8-bit improvements of 3.2%/3.0% at ef 180/340, with identical ordered result and distance hashes on fixed indexes. Those measurements preceded the tail guard; the final guard was correctness- and assembly-checked, without a new end-to-end performance claim.Compatibility
No public API, persisted index-format, or dependency changes. Existing finalized indexes remain compatible. Construction now excludes unused lanes from partially filled neighborhoods.