jimczi commented on code in PR #16705:
URL: https://github.com/apache/lucene/pull/16705#discussion_r4093561026


##########
lucene/core/src/java/org/apache/lucene/index/KnnVectorValues.java:
##########
@@ -50,12 +50,47 @@ public int ordToDoc(int ord) {
   }
 
   /**
-   * Prefetches the provided ordinals
+   * Prefetches {@code count} consecutive vectors starting at the given 
ordinal, so that later calls
+   * to read them are more likely to hit memory. Implementations should start 
the reads and return
+   * without waiting for them, and are free to prefetch fewer vectors than 
asked for, including none
+   * at all. {@code count} is clamped to the number of vectors remaining after 
{@code ord}. The
+   * default implementation is a no-op.
+   *
+   * @param ord the ordinal of the first vector to prefetch
+   * @param count how many consecutive vectors to prefetch, starting at {@code 
ord}
+   * @return the number of vectors a prefetch was actually issued for, {@code 
0} if none, in which
+   *     case the caller gains nothing by deferring the reads
+   */
+  public int prefetch(int ord, int count) throws IOException {
+    return 0;
+  }

Review Comment:
   prefetch isn't a read, it starts the load and comes back, so a single ord is 
useful as long as you read it later. That's exactly what the rerank does, issue 
all the candidates first, score after. If you read straight away then yes it 
buys nothing, and that case is already handled, the array version skips a lone 
ord. `StoredFields#prefetch(int docID)` has the same single item shape.
   
   I also think `(ord, count)` is the right primitive because it's what 
`IndexInput#prefetch(offset, length)` takes, and vectors are fixed size and 
contiguous by ord. You can build the array version on top of it, which is what 
the default does now, but not the other way around. With only the array version 
every impl has to find the runs itself, and the one we had didn't, it issued 
one madvise per ord. And for a plain range you'd have to allocate an int[] just 
to say two numbers.
   



##########
lucene/core/src/java/org/apache/lucene/index/KnnVectorValues.java:
##########
@@ -50,12 +50,47 @@ public int ordToDoc(int ord) {
   }
 
   /**
-   * Prefetches the provided ordinals
+   * Prefetches {@code count} consecutive vectors starting at the given 
ordinal, so that later calls
+   * to read them are more likely to hit memory. Implementations should start 
the reads and return
+   * without waiting for them, and are free to prefetch fewer vectors than 
asked for, including none
+   * at all. {@code count} is clamped to the number of vectors remaining after 
{@code ord}. The
+   * default implementation is a no-op.
+   *
+   * @param ord the ordinal of the first vector to prefetch
+   * @param count how many consecutive vectors to prefetch, starting at {@code 
ord}
+   * @return the number of vectors a prefetch was actually issued for, {@code 
0} if none, in which
+   *     case the caller gains nothing by deferring the reads
+   */
+  public int prefetch(int ord, int count) throws IOException {
+    return 0;
+  }
+
+  /**
+   * Prefetches the provided ordinals. Ordinals that are consecutive in the 
array are prefetched
+   * together with a single call to {@link #prefetch(int, int)}.
    *
    * @param ordsToPrefetch a list of ordinals to prefetch
    * @param numOrds number of ords to prefetch from ordsToPrefetch array
    */
-  public void prefetch(final int[] ordsToPrefetch, int numOrds) throws 
IOException {}
+  public void prefetch(final int[] ordsToPrefetch, int numOrds) throws 
IOException {
+    if (ordsToPrefetch == null) {
+      return;
+    }
+    final int count = Math.min(numOrds, ordsToPrefetch.length);
+    if (count <= 1) {
+      // A single ord is read right after this call, so prefetching it buys no 
overlap. Callers that
+      // do want a lone value loaded ahead of time should call prefetch(ord, 
1) directly.
+      return;
+    }
+    int i = 0;
+    while (i < count) {
+      final int runStart = i++;
+      while (i < count && ordsToPrefetch[i] == ordsToPrefetch[i - 1] + 1) {

Review Comment:
   I don't think `KnnVectorValues` can decide that. Whether 2 and 4 are on the 
same page depends on `byteSize`, which only the impl knows. At 1024 dims fp32 a 
vector is 4KB so those ords never share a page, at 128 byte dims you get 32 per 
page and merging is obviously right.
   
   What I'd rather do is let `MemorySegmentIndexInput#prefetch` remember the 
last page aligned range it advised and skip a call that falls inside it. An 
IndexInput is single threaded and cloned per thread, so no locking needed. That 
covers 2, 4, 6, 8 without any gap heuristic up here.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to