-
Notifications
You must be signed in to change notification settings - Fork 25.8k
Enable zero-copy SIMD vector scoring on searchable snapshots (frozen tier) #141718
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
129 commits
Select commit
Hold shift + click to select a range
8c42e95
Use searchable snapshot in vector jmh
ChrisHegarty c938f1a
itr
ChrisHegarty 0b80022
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 0828cd2
itr
ChrisHegarty 9a97011
itr
ChrisHegarty fc23dee
typo
ChrisHegarty bc4bbf5
itr
ChrisHegarty 8056dc2
Merge branch 'main' into bbq_vec_ops
ChrisHegarty a15dc37
revert
ChrisHegarty b620ca7
revert
ChrisHegarty d1ad5fd
[CI] Auto commit changes from spotless
1d10b8b
itr
ChrisHegarty e776c72
Merge remote-tracking branch 'chegar/bbq_vec_ops' into bbq_vec_ops
ChrisHegarty f63bbb1
fix bench
ChrisHegarty 04ae17d
Merge branch 'main' into bbq_vec_ops
ChrisHegarty f92e1ce
Bump the default BlobCacheBufferIndexInput buffer from 1k to 4k for s…
ChrisHegarty 41d72f3
Merge branch 'main' into default_blob_cache_input_buffer_size
ChrisHegarty a81bd5d
Merge branch 'main' into default_blob_cache_input_buffer_size
ChrisHegarty 7dd999e
refactor
ChrisHegarty 7afec0e
itr
ChrisHegarty 21d1116
itr
ChrisHegarty 4bf0c59
Enable searchable snapshot directory in vector tests and benchmarks
ChrisHegarty 54c8583
Merge branch 'main' into ss_in_vec_tests
ChrisHegarty 9efc9a5
Merge branch 'main' into ss_in_vec_tests
ChrisHegarty 246506b
itr
ChrisHegarty fc14459
Merge remote-tracking branch 'chegar/default_blob_cache_input_buffer_…
ChrisHegarty 177fa8e
Merge branch 'main' into default_blob_cache_input_buffer_size
ChrisHegarty 9faef6b
itr
ChrisHegarty 7e6971e
Merge remote-tracking branch 'chegar/default_blob_cache_input_buffer_…
ChrisHegarty 50a4b37
itr
ChrisHegarty 7166bdb
Merge remote-tracking branch 'chegar/ss_in_vec_tests' into bbq_vec_ops
ChrisHegarty 703dea5
Merge branch 'default_blob_cache_input_buffer_size' into bbq_vec_ops
ChrisHegarty 2323933
[CI] Auto commit changes from spotless
39c35ec
itr
ChrisHegarty 1a95e35
Merge remote-tracking branch 'chegar/bbq_vec_ops' into bbq_vec_ops
ChrisHegarty 93f3af2
reverts
ChrisHegarty 15ea286
itr
ChrisHegarty d1c5873
Merge remote-tracking branch 'chegar/ss_in_vec_tests' into ss_in_vec_…
ChrisHegarty 55f4e2c
itr
ChrisHegarty 8c773a5
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 96d956b
Merge branch 'main' into ss_in_vec_tests
ChrisHegarty d01df59
ref count
ChrisHegarty 43c9f25
eager close
ChrisHegarty f539831
private memory segment
ChrisHegarty 4187028
[CI] Auto commit changes from spotless
a0873b9
export
ChrisHegarty f663a8e
Merge remote-tracking branch 'chegar/bbq_vec_ops' into bbq_vec_ops
ChrisHegarty 5b9603e
typo
ChrisHegarty 3a4b50f
use temp files in SearchableSnapshotDirectoryFactory
ChrisHegarty e4c4e0a
final
ChrisHegarty 6adff83
use snap in knnIndexTester
ChrisHegarty 7688d5d
Merge branch 'main' into ss_in_vec_tests
ChrisHegarty d574423
revert
ChrisHegarty 04fa7e8
fix file length
ChrisHegarty 0205c44
use a fs blob container
ChrisHegarty 29a35d5
Merge branch 'main' into ss_in_vec_tests
ChrisHegarty 5ce73a9
fix shared bytes leak
ChrisHegarty 5d01670
Merge branch 'main' into ss_in_vec_tests
ChrisHegarty 37b1787
Merge branch 'main' into ss_in_vec_tests
ChrisHegarty 6ca3230
Merge branch 'ss_in_vec_tests' into bbq_vec_ops
ChrisHegarty c1f9a19
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 25c99db
Merge remote-tracking branch 'upstream/main' into bbq_vec_ops
ChrisHegarty 44fb563
[CI] Auto commit changes from spotless
3639bab
revert
ChrisHegarty cd16719
revert
ChrisHegarty d218432
revert
ChrisHegarty 8c8e5dd
[CI] Auto commit changes from spotless
0ff7d47
update int7 for centroid sccoring and knn index tester
ChrisHegarty 51c8472
wither
ChrisHegarty d3ac439
add missing file
ChrisHegarty ee06e44
Merge remote-tracking branch 'upstream/main' into bbq_vec_ops
ChrisHegarty 5363ee7
move to core
ChrisHegarty a0367eb
[CI] Auto commit changes from spotless
8c93a25
itr
ChrisHegarty 1296a72
itr
ChrisHegarty 019f57e
Merge remote-tracking branch 'chegar/bbq_vec_ops' into bbq_vec_ops
ChrisHegarty c0cbf45
remove transitive
ChrisHegarty 3b2546b
more tests
ChrisHegarty efd8169
itr
ChrisHegarty cefd951
more bits
ChrisHegarty 21854dc
remove memorysegment
ChrisHegarty b42db0c
itr
ChrisHegarty 4399355
itr
ChrisHegarty cf6bdc1
itr
ChrisHegarty 822f9fd
stored metrics
ChrisHegarty 1c8314c
itr
ChrisHegarty efd70d2
some reverts
ChrisHegarty 07c8069
more reverts
ChrisHegarty 95b65d1
more reverts
ChrisHegarty 48c18c7
itr
ChrisHegarty 62b5095
itr
ChrisHegarty 926dbcb
minor
ChrisHegarty e5a5598
itr
ChrisHegarty 58ecaa4
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 2f87d0e
extensible knnindextester
ChrisHegarty 17c7541
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 3ce2f87
fix acceptable input types
ChrisHegarty 7ddbfa1
Merge remote-tracking branch 'chegar/bbq_vec_ops' into bbq_vec_ops
ChrisHegarty 6e1c7ec
fix
ChrisHegarty 8968d7c
Merge remote-tracking branch 'upstream/main' into bbq_vec_ops
ChrisHegarty c98c67a
[CI] Auto commit changes from spotless
39b6cf0
fix
ChrisHegarty 7afcd16
fix
ChrisHegarty 9ac050a
javadoc
ChrisHegarty c2bf25c
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 588463d
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 748f491
Merge remote-tracking branch 'upstream/main' into bbq_vec_ops
ChrisHegarty 927afb3
fix :qa:vector:checkVec
ChrisHegarty 432aac5
fix :qa:vector:checkVec
ChrisHegarty a8f056f
Merge branch 'main' into fix_qa_vector_checkVec
ChrisHegarty 718ea9d
Merge branch 'main' into bbq_vec_ops
ChrisHegarty a183a74
[CI] Auto commit changes from spotless
02467a6
itr
ChrisHegarty a372af9
Merge remote-tracking branch 'chegar/fix_qa_vector_checkVec' into bbq…
ChrisHegarty 79f69ec
Merge remote-tracking branch 'chegar/bbq_vec_ops' into bbq_vec_ops
ChrisHegarty 9462242
Move DirectAccessInput interface from BlobCacheBufferedIndexInput t…
ChrisHegarty 0342b44
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 91d7b54
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 7b90c4c
remove atomic
ChrisHegarty cf65b22
Merge remote-tracking branch 'chegar/bbq_vec_ops' into bbq_vec_ops
ChrisHegarty 75c3ba6
rename and check input type in more places
ChrisHegarty fc4eca5
Update docs/changelog/141718.yaml
ChrisHegarty c37998f
update MemorySegmentES91OSQVectorsScorer
ChrisHegarty 57c8469
Merge remote-tracking branch 'chegar/bbq_vec_ops' into bbq_vec_ops
ChrisHegarty 59208b8
Merge remote-tracking branch 'upstream/main' into bbq_vec_ops
ChrisHegarty e03e5fd
use a scratch buffer for on-heap
ChrisHegarty 7f67f81
Merge branch 'main' into bbq_vec_ops
ChrisHegarty 7407119
fix
ChrisHegarty d2ced8b
revert
ChrisHegarty File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| area: Vector Search | ||
| issues: [] | ||
| pr: 141718 | ||
| summary: Enable zero-copy SIMD vector scoring on searchable snapshots (frozen tier) | ||
| type: enhancement |
40 changes: 40 additions & 0 deletions
40
libs/core/src/main/java/org/elasticsearch/core/DirectAccessInput.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the "Elastic License | ||
| * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
| * Public License v 1"; you may not use this file except in compliance with, at | ||
| * your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
| * License v3.0 only", or the "Server Side Public License, v 1". | ||
| */ | ||
|
|
||
| package org.elasticsearch.core; | ||
|
|
||
| import java.io.IOException; | ||
| import java.nio.ByteBuffer; | ||
|
|
||
| /** | ||
| * An optional interface that an IndexInput can implement to provide direct | ||
| * access to the underlying data as a {@link ByteBuffer}. This enables | ||
| * zero-copy access to memory-mapped data for SIMD-accelerated vector scoring. | ||
| * | ||
| * <p> The byte buffer is passed to the caller's action and is only valid for | ||
| * the duration of that call. All ref-counting and resource releases, if any, | ||
| * is handled internally. | ||
| */ | ||
| public interface DirectAccessInput { | ||
|
|
||
| /** | ||
| * If a direct byte buffer view is available for the given range, passes it | ||
| * to {@code action} and returns {@code true}. Otherwise returns | ||
| * {@code false} without invoking the action. | ||
| * | ||
| * <p>The byte buffer is read-only and valid only for the duration of the | ||
| * action. Callers must not retain references to it after the action returns. | ||
| * | ||
| * @param offset the byte offset within the input | ||
| * @param length the number of bytes requested | ||
| * @param action the action to perform with the byte buffer | ||
| * @return {@code true} if a buffer was available and the action was invoked | ||
| */ | ||
| boolean withByteBufferSlice(long offset, long length, CheckedConsumer<ByteBuffer, IOException> action) throws IOException; | ||
| } | ||
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
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
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
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
114 changes: 114 additions & 0 deletions
114
libs/simdvec/src/main21/java/org/elasticsearch/simdvec/internal/IndexInputUtils.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the "Elastic License | ||
| * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
| * Public License v 1"; you may not use this file except in compliance with, at | ||
| * your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
| * License v3.0 only", or the "Server Side Public License, v 1". | ||
| */ | ||
| package org.elasticsearch.simdvec.internal; | ||
|
|
||
| import org.apache.lucene.store.FilterIndexInput; | ||
| import org.apache.lucene.store.IndexInput; | ||
| import org.apache.lucene.store.MemorySegmentAccessInput; | ||
| import org.elasticsearch.core.CheckedFunction; | ||
| import org.elasticsearch.core.DirectAccessInput; | ||
|
|
||
| import java.io.IOException; | ||
| import java.lang.foreign.MemorySegment; | ||
| import java.util.function.IntFunction; | ||
|
|
||
| /** | ||
| * Utility for obtaining a {@link MemorySegment} view of data in an | ||
| * {@link IndexInput} and passing it to a caller-supplied action. The | ||
| * segment may come from a {@link MemorySegmentAccessInput} (mmap), | ||
| * a direct {@link java.nio.ByteBuffer} view (e.g. blob-cache), or a | ||
| * heap copy as a last resort. | ||
| * | ||
| * <p>All resource management (ref-counting, buffer release) is handled | ||
| * internally — callers never see a closeable resource. | ||
| */ | ||
| public final class IndexInputUtils { | ||
|
|
||
| private IndexInputUtils() {} | ||
|
|
||
| /** | ||
| * Obtains a memory segment for the next {@code length} bytes of the | ||
| * index input, passes it to {@code action}, and returns the result. | ||
| * The position of the index input is advanced by {@code length}. | ||
| * | ||
| * <p> This method first tries to obtain a slice via | ||
| * {@link MemorySegmentAccessInput#segmentSliceOrNull}. If that | ||
| * returns {@code null}, it tries a direct {@link java.nio.ByteBuffer} | ||
| * view via {@link DirectAccessInput}. As a last resort it copies the | ||
| * data onto the heap using a byte array obtained from | ||
| * {@code scratchSupplier}. | ||
| * | ||
| * <p> The memory segment passed to {@code action} is valid only for | ||
| * the duration of the call. Callers must not retain references to it. | ||
| * | ||
| * @param in the index input positioned at the data to read | ||
| * @param length the number of bytes to read | ||
| * @param scratchSupplier supplies a byte array of at least the requested | ||
| * length, used only on the heap-copy fallback path | ||
| * @param action the function to apply to the memory segment | ||
| * @return the result of applying {@code action} | ||
| */ | ||
| public static <R> R withSlice( | ||
| IndexInput in, | ||
| long length, | ||
| IntFunction<byte[]> scratchSupplier, | ||
| CheckedFunction<MemorySegment, R, IOException> action | ||
| ) throws IOException { | ||
| checkInputType(in); | ||
| if (in instanceof MemorySegmentAccessInput msai) { | ||
|
ChrisHegarty marked this conversation as resolved.
|
||
| long offset = in.getFilePointer(); | ||
| MemorySegment slice = msai.segmentSliceOrNull(offset, length); | ||
| if (slice != null) { | ||
| in.skipBytes(length); | ||
| return action.apply(slice); | ||
| } | ||
| } | ||
| if (in instanceof DirectAccessInput dai) { | ||
| long offset = in.getFilePointer(); | ||
| @SuppressWarnings("unchecked") | ||
| R[] result = (R[]) new Object[1]; | ||
|
ChrisHegarty marked this conversation as resolved.
|
||
| boolean available = dai.withByteBufferSlice(offset, length, bb -> { | ||
| in.skipBytes(length); | ||
| result[0] = action.apply(MemorySegment.ofBuffer(bb)); | ||
| }); | ||
| if (available) { | ||
| return result[0]; | ||
| } | ||
| } | ||
| return action.apply(copyOnHeap(in, Math.toIntExact(length), scratchSupplier)); | ||
| } | ||
|
|
||
| /** | ||
| * Checks that a {@link FilterIndexInput} wrapper also implements | ||
| * {@link MemorySegmentAccessInput} or {@link DirectAccessInput}, | ||
| * so that zero-copy access is preserved through the wrapper chain. | ||
| */ | ||
| public static void checkInputType(IndexInput in) { | ||
| if (in instanceof FilterIndexInput && (in instanceof MemorySegmentAccessInput || in instanceof DirectAccessInput) == false) { | ||
| throw new IllegalArgumentException( | ||
| "IndexInput is a FilterIndexInput (" | ||
| + in.getClass().getName() | ||
| + ") that does not implement MemorySegmentAccessInput or DirectAccessInput. " | ||
| + "Ensure the wrapper implements DirectAccessInput or is unwrapped before constructing the scorer." | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Reads the given number of bytes from the current position of the | ||
| * given IndexInput into a heap-backed memory segment. The returned | ||
| * segment is sliced to exactly {@code bytesToRead} bytes, even if | ||
| * the underlying array is larger. | ||
| */ | ||
| private static MemorySegment copyOnHeap(IndexInput in, int bytesToRead, IntFunction<byte[]> scratchSupplier) throws IOException { | ||
| byte[] buf = scratchSupplier.apply(bytesToRead); | ||
| in.readBytes(buf, 0, bytesToRead); | ||
| return MemorySegment.ofArray(buf).asSlice(0, bytesToRead); | ||
| } | ||
| } | ||
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.