Stiching Faiss104ScalarQuantizedKnnVectorsWriter to MemOptimizedScalarQuantizedIndexBuildStrategy#3185
Conversation
| int totalLiveDocs; | ||
| SegmentWriteState segmentWriteState; | ||
| boolean isFlush; | ||
| Map<String, Object> buildStrategyParams; |
There was a problem hiding this comment.
This is parameters to be passed down to build strategy from VectorsWriter.
| @@ -196,10 +196,7 @@ private void writeToRepository(RepositoryContext repositoryContext, BuildIndexPa | |||
| ); | |||
There was a problem hiding this comment.
No major changes in this file.
| @@ -73,7 +73,7 @@ public void buildAndWriteIndex(final BuildIndexParams indexInfo) throws IOExcept | |||
| } | |||
There was a problem hiding this comment.
No major changes
| @@ -47,15 +47,15 @@ public static MemOptimizedNativeIndexBuildStrategy getInstance() { | |||
| * enabled, the vectors are quantized before being transferred off-heap. Once all vectors are transferred, they are | |||
There was a problem hiding this comment.
No major changes
| import static org.opensearch.knn.index.vectorvalues.KNNVectorValuesFactory.getVectorValuesSupplier; | ||
|
|
||
| @Log4j2 | ||
| public abstract class AbstractNativeEnginesKnnVectorsWriter extends KnnVectorsWriter { |
There was a problem hiding this comment.
Will add detailed java doc.
75b695a to
5e3d623
Compare
…rQuantizedIndexBuildStrategy Signed-off-by: Dooyong Kim <kdooyong@amazon.com>
5e3d623 to
abf26a4
Compare
| throw e; | ||
| } | ||
|
|
||
| final Object flatVectorsReaderObj = ((IOSupplier<?>) flatVectorsReaderSupplierObj).get(); |
There was a problem hiding this comment.
Any reason to not move all of this down to the format classes? We are breaking separation of concerns now with this flow. Passing down general objects and doing typecasting in a hot code path - I feel this is a concern of readers and writers.
There was a problem hiding this comment.
Sorry not following, I believe since this is the build strategy, so it has faiss bbq index build responsibility.
In here, FlacVectorsReader (i.e. .veb reader) is required to build Faiss BBQ index.
So the logic is to load quantized vectors into C++ off-heap, so that C++ HNSW can perform distance calculation on them.
I can't think of another way to put this in format layer or writer layer as this is a part of building process.
There was a problem hiding this comment.
@0ctopus13prime earlier there we had SeGMENT STATE all part of This change , but now we wrapped into Supplier and passing the Supplier with All Segment State make no difference with earlier code to this.
There was a problem hiding this comment.
But what it tries to load is for the new segment that's being baked right now.
So SegmentWriteState does not have any references to it, because .veb is new one being built.
There was a problem hiding this comment.
I understand the strategy needs quantized vectors to build the Faiss BBQ index that's not in question. The concern is about where the Lucene reader opening and reflection logic lives, not whether it happens.
The issue is consistency with the existing strategy contract. Every other strategy in this codebase receives its input data through typed fields on BuildIndexParams:
DefaultIndexBuildStrategy → indexInfo.getKnnVectorValuesSupplier().get()
MemOptimizedNativeIndexBuildStrategy → indexInfo.getKnnVectorValuesSupplier().get()
None of them open Lucene readers, do reflection, or manage reader lifecycles. They receive prepared data and build an index.
Can we pass the result as a typed Supplier on BuildIndexParams — the same pattern as knnVectorValuesSupplier. The strategy then just calls indexInfo.getQuantizedVectorValuesSupplier().get() and does the native build. This keeps all Lucene format I/O in the writer layer and all native index construction in the strategy layer.
I do have a sample implementation here: kotwanikunal@aef426b#diff-f8c4eb218bf94ceee3be08f3489f3736f701652b0a4273d8b3cb103548eb2c13
There was a problem hiding this comment.
I understand your concern, but that's slow since it first copies vectors to std::vector first, then it copies what's in std::vector to Faiss index builder.
Even removed this double copy, from the benchmark this bbq indexing is showing -5% indexing throughput decrease compared to BQ. And if we move to the existing way, then the gap will be widen.
Furthermore, it's designed to pass quantized vectors, not designed for passing quantized vectors + correction factors I believe.
I think it's worth to sacrificing the vectors loading abstraction for better performance.
Please share your thoughts on this.
There was a problem hiding this comment.
The performance concern about the native transfer path is valid and completely separate from the ask is what I think. The suggestion is not that you use the existing VectorTransfer/KNNVectorValues for the data transfer — the custom passBBQVectorsWithCorrectionFactors JNI path with the packed layout can be in the strategy.
The ask is smaller: move the lines that open the FlatVectorsReader from the strategy into the writer. The strategy still receives QuantizedByteVectorValues and does the exact same native transfer it does today. No change to the JNI path, no double copy, no performance impact.
Out of the strategy:
// These lines move to the writer
Object supplier = indexInfo.getBuildStrategyParams().get(KEY);
IOSupplier<?> ioSupplier = (IOSupplier<?>) supplier;
FlatVectorsReader reader = (FlatVectorsReader) ioSupplier.get();
FloatVectorValues fvv = reader.getFloatVectorValues(field);
Field f = fvv.getClass().getDeclaredField("quantizedVectorValues");
f.setAccessible(true);
QuantizedByteVectorValues qv = (QuantizedByteVectorValues) f.get(fvv);
Into the strategy (unchanged):
// Strategy still does all the native work exactly as before
QuantizedByteVectorValues qv = indexInfo.getQuantizedVectorValuesSupplier().get();
transferQuantizedVectors(indexMemoryAddress, qv, quantizedVecBytes, knnEngine);
buildGraph(indexMemoryAddress, knnVectorValues, knnEngine);
The transferQuantizedVectors method, the batch packing, the passBBQVectorsWithCorrectionFactors call, the addDocsToBBQIndex call — all of that stays exactly where it is.
There was a problem hiding this comment.
Ah! got it, somehow i misread your comments.
Good point, will update in the next rev.
...ava/org/opensearch/knn/index/codec/KNN1040Codec/Faiss104ScalarQuantizedKnnVectorsWriter.java
Show resolved
Hide resolved
| */ | ||
| @Log4j2 | ||
| public class NativeEngines990KnnVectorsWriter extends KnnVectorsWriter { | ||
| public class NativeEngines990KnnVectorsWriter extends AbstractNativeEnginesKnnVectorsWriter { |
There was a problem hiding this comment.
Can we not touch this class as part of this , It will may increase blast Radius? we can have next attemept to refactor this.
There was a problem hiding this comment.
Will need votes for this, I got feedbacks that avoid copy-and-paste code as possible
@kotwanikunal @navneet1v
Can you share your thoughts on this?
There was a problem hiding this comment.
Intent is right ... If we are okay to test all the code path we are touching as part of this , should be fine
| int totalLiveDocs; | ||
| SegmentWriteState segmentWriteState; | ||
| boolean isFlush; | ||
| Map<String, Object> buildStrategyParams; |
There was a problem hiding this comment.
What Object Represent here ?
There was a problem hiding this comment.
It's a general reference (i.e. similar to void* in C++), it's build strategy's responsibility to cast the Object with key.
There was a problem hiding this comment.
Yeah my question is What are differnt types we are expoecting here , Why it can not be concrete
There was a problem hiding this comment.
so far the only type that's being used is IOSupplier.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## feature/faiss-bbq #3185 +/- ##
=======================================================
+ Coverage 82.41% 82.44% +0.03%
- Complexity 3997 4036 +39
=======================================================
Files 431 437 +6
Lines 14939 15042 +103
Branches 1891 1904 +13
=======================================================
+ Hits 12312 12402 +90
- Misses 1861 1866 +5
- Partials 766 774 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Description
This PR introduces the Faiss BBQ (Better Binary Quantization) indexing pipeline and refactors the native engine writer hierarchy to share common flush/merge logic.
New BBQ codec classes:
Refactoring:
Bug fixes found during development:
Related Issues
Resolves #[Issue number to be closed when this PR is merged]
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.