Repository navigation
Conversation
A DiskANN search quantized a query that was not float32 through diskann_distance_quantized(), which read it as floats, four times its bytes: every insert into an int8 column, whose graph insertion searches with the new vector, read past it. The neighbors of an int8 column were stored by copying the start of their vectors, so under the binary quantizer a neighbor's bits were its first bytes. diskann_quantize_element_vector() quantizes a vector of either element type: a float32 vector as before, and an int8 vector as itself under the int8 quantizer or as the bits of its elements above 0 under the binary quantizer, as a float32 vector is. The query and every neighbor go through it, and the wrapper that quantized on the fly is gone.
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.
An
int8column indexed by DiskANN reads past the vectors it quantizes, and stores its neighbors' quantized vectors wrong.diskann_search()quantizes the query only when it isfloat32. For anint8query it callsdiskann_distance_quantized(), which casts the vector toconst f32 *and quantizes it as floats, reading four times its bytes. Every insert searches the graph with the new vector, so every insert into anint8column reads past it. Built with AddressSanitizer, five inserts into anint8[2048]column withneighbor_quantizer=int8:The neighbors of an
int8column are stored by copying the start of their vectors (thememcpybeside eachdiskann_quantize_vector()call). Under the int8 quantizer that copy is the vector itself, but under the binary quantizer a neighbor's bits become its firstdimensions / 8bytes rather than its signs: in a 12-rowint8[16]table withneighbor_quantizer=binary, none of the 91 stored neighbor vectors holds its row's sign bits. Under the int8 quantizer the query distances are garbage, so the search goes astray: over 10 queries on 100 rows ofint8[64], withsearch_list_size=128so the list can hold every row, it returns 28 of the exact 100 nearest.This adds
diskann_quantize_element_vector(), which quantizes a vector of either element type a DiskANN column accepts: afloat32vector asdiskann_quantize_vector()does, and anint8vector as itself under the int8 quantizer and as the bits of its elements above 0 under the binary quantizer, as for afloat32vector. The query and every stored neighbor go through it, anddiskann_distance_quantized(), which nothing else calls, is removed.Two tests in test-diskann.py fail on main and pass here:
test_diskann_int8_column_knn_matches_exact(the exact 10 nearest rows for 10 queries) andtest_diskann_int8_column_binary_neighbors_are_sign_bits(every valid neighbor slot holds its row's sign bits). The Python suite passes (241 passed, 66 skipped), test-diskann.py passes against an AddressSanitizer and UndefinedBehaviorSanitizer build, the five-insert case above runs clean under it, and the build's warnings are main's.#311 clamps the int8 quantizer's conversion inside
diskann_quantize_vector(), which this leaves alone; it merges cleanly with #311 and with every other open PR that touches the DiskANN code.Origin. Found in the DiskANN port to photostructure/sqlite-vec, photostructure#11 (cd53413), which lists it among the port's differences from upstream; the change and its tests are written here for asg017's main. No open or closed PR or issue here makes the same change.