Skip to content

Give every DiskANN result its exact distance - #345

Open
MayCXC wants to merge 1 commit into
asg017:mainfrom
MayCXC:diskann-exact-distances
Open

MayCXC wants to merge 1 commit into
asg017:mainfrom
MayCXC:diskann-exact-distances

Conversation

@MayCXC

@MayCXC MayCXC commented Oct 23, 2026 •

Copy link
Copy Markdown

A DiskANN KNN query returns distances that are not its rows' distances, in an order that is not theirs.

diskann_search() ranks the neighbors it reaches by their quantized distances, and gives each candidate it visits its exact distance by calling diskann_candidate_list_insert() again with that distance. For a rowid already in the list, that function only ever lowers the distance ("Update distance if better"), so a candidate whose exact distance is larger than its quantized one keeps the quantized one, which is then reported as its distance and decides its rank. Under the int8 quantizer with cosine distance the quantized distance is often the smaller:

create virtual table t using vec0(emb float[32] distance_metric=cosine indexed by diskann(neighbor_quantizer=int8));
-- 300 rows of random gaussian vectors
select rowid, distance, vec_distance_cosine(emb, :q) from t where emb match :q and k = 10;

Over 30 such queries on main, 202 of the 300 rows come back with a distance other than vec_distance_cosine(emb, :q) (one row is reported at 0.461 where its distance is 1.302), and none of the 30 lists is in the order of the rows' distances.

diskann_candidate_list_confirm() gives a visited candidate its exact distance, larger or smaller than the quantized one, moves it to its place in the list, and marks it confirmed, which replaces the insert and the loop that set confirmed after it. A candidate the list dropped after it was visited comes back still visited when its exact distance ranks inside the list; the insert it replaces would have brought it back unvisited, to be visited a second time. diskann_candidate_list_insert() keeps its lower-only update for the quantized distances, where a row reached from two neighbors keeps the better estimate.

test_diskann_result_distances_are_exact in test-diskann.py runs the 30 queries above and checks each result's distance against vec_distance_cosine() and the order of each list. It fails on main and passes here; the Python suite passes (240 passed, 66 skipped), test-diskann.py passes against an AddressSanitizer and UndefinedBehaviorSanitizer build, and the build's warnings are main's.

It merges cleanly with every open PR that touches the DiskANN code, #344 included.

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 test are written here for asg017's main. No open or closed PR or issue here makes the same change.

A DiskANN search ranks the neighbors it reaches by quantized distance,
then gives each candidate it visits its exact distance through
diskann_candidate_list_insert(), which only ever lowers a distance. A
candidate whose exact distance was larger than its quantized one kept
the quantized one, so the results came back with distances that were
not theirs, in an order that was not the exact one.

diskann_candidate_list_confirm() replaces a visited candidate's distance
with its exact one, larger or smaller, moves it to its place, and
confirms it; a candidate the list dropped after it was visited returns
visited, when it still ranks inside the list.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant