-
Notifications
You must be signed in to change notification settings - Fork 169
Enable optimistic search to memory optimized search. #2933
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
base: feature/fp16-faiss-bulk
Are you sure you want to change the base?
Enable optimistic search to memory optimized search. #2933
Conversation
src/main/java/org/opensearch/knn/index/query/nativelib/NativeEngineKnnVectorQuery.java
Show resolved
Hide resolved
@Vikasht34 @shatejas |
Will look into this PR :- Tomorrow Morning |
5b006af
to
1e09bf0
Compare
); | ||
} | ||
|
||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic has been moved to approximateSearch
* An immutable, empty {@link BitSet} implementation used to represent | ||
* the absence of filter bits without incurring null checks or allocations. | ||
*/ | ||
public static final BitSet MATCH_ALL_BIT_SET = new BitSet() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious why we are not uysing Lucene's MathAllBits or MatcNoBits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could not use both, as it's sub class of Bits
while we need BitSet in here. 😵💫
Since optimistic search will call approximateSearch
twice, we need to keep BitSet
for reusing.
} | ||
|
||
@Override | ||
public int length() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we doing any iteration on Bitset , this gooona break if we are doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only place using this one is when we're getting siblings in nested case.
In there, we don't do iteration.
There are caveats to doing this,
I think 1 is a concern which needs discussion, 2 is manageable with some extra logic to keep behavior consistent, 3 isn't a big deal |
@shatejas from a user perspective all of this is a breaking change if we are making Lucene on Faiss default. So this needs to be documented in the docs to clearly callout the behavior and how to mitigate this. Along with this, we should ensure that older indices are still on the same non memory optimized based search so that upgrades are seamless. We have already seen GH issues in part where changes in range of cosine scores lead to issues with users. #2561 |
import java.util.List; | ||
|
||
@UtilityClass | ||
public class Optimistic2ndSearchUtils { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use better names for this class. 2ndSearchUtils
what is first search utils? and why this class is not part of the same class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think 2nd
is bit misleading.. will find a better name for that.
*/ | ||
@Log4j2 | ||
@RequiredArgsConstructor | ||
public class ReentrantKnnCollectorManager implements KnnCollectorManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is a copy/has taken references from https://github.com/apache/lucene/blob/71e822e6240878018a6ff3c28381a0d88bebdc72/lucene/core/src/java/org/apache/lucene/search/AbstractKnnVectorQuery.java#L368
It will be better to mention this somewhere in this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good, will update in the next rev.
@Setter | ||
private KnnCollectorManager optimistic2ndKnnCollectorManager; | ||
|
||
public static class OptimisticKnnCollectorManager implements KnnCollectorManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we move this to a separate file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, will update in the next rev.
public PerLeafResult(final Bits filterBits, final TopDocs result) { | ||
this.filterBits = filterBits == null ? new Bits.MatchAllBits(0) : filterBits; | ||
// Indicates whether this result was produced via exact or approximate search. | ||
private final SearchMode searchMode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the use of this parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimistic search would do deep dive HNSW search with acquired top k results as seeds. And this will not be needed if the results acquired via exact search. Hence having search mode here, and let it bypass the second search if possible.
* An immutable, empty {@link BitSet} implementation used to represent | ||
* the absence of filter bits without incurring null checks or allocations. | ||
*/ | ||
public static final BitSet MATCH_ALL_BIT_SET = new BitSet() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
* @return a {@link TopDocs} object containing the top {@code k} approximate search results | ||
* @throws IOException if an error occurs while reading index data or accessing vector fields | ||
*/ | ||
public TopDocs approximateSearch( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why we are making this function public?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need this particular function in optimistic second search. Otherwise, if using searchLeaf, then we will end up building filter bitset twice.
We are brining in a lot of code from Lucene. Please mention the source of the code for better maintainability. One way I would think is to move the class to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks Good !! Clean Code and Very Concise !! Thanks
Signed-off-by: Dooyong Kim <[email protected]>
1e09bf0
to
1861e8c
Compare
Description
RFC : #2924
Enable optimistic search for memory optimized search and deprecate MultiLeafKnnCollector which has an early termination logic.
This PR has three big changes:
Now, when memory-optimized search is enabled, all queries use
NativeEngineKnnVectorQuery
.KnnQuery
, which only provides aScorerSupplier
and performs search within a single leaf segment (with the resultingScorer
being consumed by an externalBulkScorer
under the standard Lucene search flow). But optimistic search requires coordination across segments. It needs to run an initial (first-phase) search, then identify and revisit only the segments likely to contain promising results.To support this coordinated two-phase process,
NativeEngineKnnVectorQuery
is a more suitable entry point thanKnnQuery
.Backported Lucene components required for optimistic search, specifically:
2.1. ReentrantKnnCollectorManager
2.2. SeededMappedDISI
2.3. SeededTopDocsDISI
Related Issues
Resolves #[Issue number to be closed when this PR is merged]
#2924
Check List
--signoff
.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.