diff --git a/DESIGN.md b/DESIGN.md index 04d21a6..f0a2279 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -160,9 +160,9 @@ from the record it has already read rather than from a second lookup. `RowStoringIndex.isDeleted()` recognises a tombstone. A structure holding its own form of a row records the tombstone there too: the matrix index in the unilateral values it scores against, and an inverted index in the indexed form -verification reads. The unilateral values an inverted index orders its lists by are left -alone, since candidate generation prunes against them and an order it cannot -compare would stop pruning working. +verification reads. The unilateral values an inverted index orders its lists by +are left alone, since candidate generation prunes against them and an order it +cannot compare would stop pruning working. An update is a delete of the old version followed by an insert of the new one under the same `rowNum`, so the active cache always holds the latest version. @@ -597,6 +597,12 @@ the bound, so one adding no more rows than the bound never builds a queue. The dot products of a query are reused rather than allocated for each query, since they are as long as the matrix has rows. +Selecting raises its minimum similarity as its heap fills, as a scan does, so a +row that cannot reach what the heap already holds is rejected before a result +is made for it. A query asking for the best rows of the whole matrix otherwise +makes one result per row and lets the heap discard almost all of them, which +was measured to cost more than the multiply that produced the dot products. + Selecting runs on the thread that asked for the query, not on the thread that performed the multiply, so several queries select at once and overlap the following multiply. Performing it inside the multiply would serialize the one diff --git a/src/main/java/com/uber/ussi/searchablestructure/index/matrix/DotProductRows.java b/src/main/java/com/uber/ussi/searchablestructure/index/matrix/DotProductRows.java index d92c355..8debc72 100644 --- a/src/main/java/com/uber/ussi/searchablestructure/index/matrix/DotProductRows.java +++ b/src/main/java/com/uber/ussi/searchablestructure/index/matrix/DotProductRows.java @@ -1,6 +1,7 @@ /* AUTHOR: Ahmed Metwally (ametwally@uber.com) */ package com.uber.ussi.searchablestructure.index.matrix; +import com.uber.ussi.searchablestructure.result.ResultHeaps; import com.uber.ussi.searchablestructure.result.RowNumAndSimilarity; import com.uber.ussi.utils.BoundedSizeMaxHeap; @@ -12,18 +13,25 @@ private DotProductRows() {} /** * Adds every row reaching the minimum similarity. A deleted row reaches nothing, since the * similarity derived from its unilateral value is not a number. + * + *
The minimum rises as the heap fills, so a row that cannot reach what the heap already
+ * holds is rejected before a result is made for it. Without that, a query asking for the best
+ * rows of the whole matrix makes one result per row and lets the heap discard almost all of
+ * them, which was measured to cost more than the multiply that produced the dot products.
*/
static void addRows(
float[] dotProducts,
MatrixRows rows,
RowSelection selection,
BoundedSizeMaxHeap