faiss 0.5.3 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/ext/faiss/ext.cpp +1 -1
- data/ext/faiss/extconf.rb +4 -4
- data/ext/faiss/index.cpp +63 -45
- data/ext/faiss/index_binary.cpp +37 -27
- data/ext/faiss/kmeans.cpp +9 -8
- data/ext/faiss/pca_matrix.cpp +9 -7
- data/ext/faiss/product_quantizer.cpp +13 -11
- data/ext/faiss/utils.cpp +4 -2
- data/ext/faiss/utils.h +4 -0
- data/lib/faiss/version.rb +1 -1
- data/lib/faiss.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +214 -82
- data/vendor/faiss/faiss/AutoTune.h +14 -1
- data/vendor/faiss/faiss/Clustering.cpp +97 -249
- data/vendor/faiss/faiss/Clustering.h +18 -0
- data/vendor/faiss/faiss/IVFlib.cpp +67 -44
- data/vendor/faiss/faiss/Index.cpp +25 -12
- data/vendor/faiss/faiss/Index.h +26 -4
- data/vendor/faiss/faiss/Index2Layer.cpp +37 -53
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +68 -61
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +36 -34
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +4 -1
- data/vendor/faiss/faiss/IndexBinary.cpp +6 -3
- data/vendor/faiss/faiss/IndexBinary.h +4 -4
- data/vendor/faiss/faiss/IndexBinaryFlat.cpp +1 -1
- data/vendor/faiss/faiss/IndexBinaryFlat.h +1 -1
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +92 -95
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +9 -3
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +45 -236
- data/vendor/faiss/faiss/IndexBinaryHash.h +6 -6
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +120 -414
- data/vendor/faiss/faiss/IndexFastScan.cpp +105 -129
- data/vendor/faiss/faiss/IndexFastScan.h +35 -24
- data/vendor/faiss/faiss/IndexFlat.cpp +216 -152
- data/vendor/faiss/faiss/IndexFlat.h +32 -14
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +88 -41
- data/vendor/faiss/faiss/IndexFlatCodes.h +7 -1
- data/vendor/faiss/faiss/IndexHNSW.cpp +299 -187
- data/vendor/faiss/faiss/IndexHNSW.h +30 -14
- data/vendor/faiss/faiss/IndexIDMap.cpp +26 -22
- data/vendor/faiss/faiss/IndexIDMap.h +9 -7
- data/vendor/faiss/faiss/IndexIVF.cpp +535 -405
- data/vendor/faiss/faiss/IndexIVF.h +47 -16
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +77 -74
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +105 -99
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +6 -3
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +379 -249
- data/vendor/faiss/faiss/IndexIVFFastScan.h +65 -60
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +41 -124
- data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +89 -138
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +3 -1
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +18 -15
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +77 -907
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +184 -122
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +3 -0
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +23 -18
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +59 -60
- data/vendor/faiss/faiss/IndexIVFRaBitQ.h +4 -3
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +564 -416
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +269 -111
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +41 -127
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
- data/vendor/faiss/faiss/IndexLSH.cpp +44 -25
- data/vendor/faiss/faiss/IndexLattice.cpp +41 -36
- data/vendor/faiss/faiss/IndexNNDescent.cpp +37 -21
- data/vendor/faiss/faiss/IndexNNDescent.h +2 -2
- data/vendor/faiss/faiss/IndexNSG.cpp +40 -23
- data/vendor/faiss/faiss/IndexNSG.h +0 -2
- data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +32 -12
- data/vendor/faiss/faiss/IndexPQ.cpp +129 -213
- data/vendor/faiss/faiss/IndexPQ.h +3 -2
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +20 -14
- data/vendor/faiss/faiss/IndexPQFastScan.h +3 -0
- data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -18
- data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +31 -43
- data/vendor/faiss/faiss/IndexRaBitQ.h +4 -3
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +135 -317
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +192 -34
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -55
- data/vendor/faiss/faiss/IndexRefine.h +4 -4
- data/vendor/faiss/faiss/IndexReplicas.cpp +6 -6
- data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +15 -14
- data/vendor/faiss/faiss/IndexRowwiseMinMax.h +1 -1
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +82 -14
- data/vendor/faiss/faiss/IndexShards.cpp +13 -13
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +21 -15
- data/vendor/faiss/faiss/MatrixStats.cpp +5 -4
- data/vendor/faiss/faiss/MetaIndexes.cpp +19 -17
- data/vendor/faiss/faiss/MetaIndexes.h +1 -1
- data/vendor/faiss/faiss/MetricType.h +29 -6
- data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
- data/vendor/faiss/faiss/SuperKMeans.h +97 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +349 -141
- data/vendor/faiss/faiss/VectorTransform.h +39 -16
- data/vendor/faiss/faiss/build.cpp +23 -0
- data/vendor/faiss/faiss/build.h +15 -0
- data/vendor/faiss/faiss/clone_index.cpp +55 -51
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +47 -47
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +11 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +38 -38
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +11 -0
- data/vendor/faiss/faiss/{cppcontrib/factory_tools.cpp → factory_tools.cpp} +6 -1
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +1 -1
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +6 -5
- data/vendor/faiss/faiss/gpu/GpuResources.h +1 -1
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +9 -9
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +4 -3
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +46 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +56 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +78 -1
- data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +72 -0
- data/vendor/faiss/faiss/gpu/test/TestUtils.h +23 -0
- data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +1 -1
- data/vendor/faiss/faiss/gpu/utils/CuvsUtils.h +21 -10
- data/vendor/faiss/faiss/gpu_metal/GpuIndexFlat.h +22 -0
- data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +35 -0
- data/vendor/faiss/faiss/gpu_metal/MetalFlatKernels.h +40 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +51 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h +65 -0
- data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +66 -0
- data/vendor/faiss/faiss/gpu_metal/MetalResources.h +79 -0
- data/vendor/faiss/faiss/gpu_metal/StandardMetalResources.h +35 -0
- data/vendor/faiss/faiss/impl/AdSampling.cpp +103 -0
- data/vendor/faiss/faiss/impl/AdSampling.h +35 -0
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +64 -34
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +10 -9
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +3 -28
- data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +244 -0
- data/vendor/faiss/faiss/impl/ClusteringHelpers.h +94 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +367 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.h +107 -0
- data/vendor/faiss/faiss/impl/CodePacker.cpp +7 -3
- data/vendor/faiss/faiss/impl/CodePacker.h +11 -3
- data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +83 -0
- data/vendor/faiss/faiss/impl/CodePackerRaBitQ.h +47 -0
- data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
- data/vendor/faiss/faiss/impl/FaissAssert.h +64 -3
- data/vendor/faiss/faiss/impl/FaissException.h +50 -3
- data/vendor/faiss/faiss/impl/HNSW.cpp +117 -351
- data/vendor/faiss/faiss/impl/HNSW.h +21 -40
- data/vendor/faiss/faiss/impl/IDSelector.cpp +15 -11
- data/vendor/faiss/faiss/impl/IDSelector.h +8 -8
- data/vendor/faiss/faiss/impl/InvertedListScannerStats.h +26 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +114 -102
- data/vendor/faiss/faiss/impl/NNDescent.cpp +63 -26
- data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +44 -26
- data/vendor/faiss/faiss/impl/NSG.h +20 -10
- data/vendor/faiss/faiss/impl/Panorama.cpp +76 -52
- data/vendor/faiss/faiss/impl/Panorama.h +265 -78
- data/vendor/faiss/faiss/impl/PdxLayout.cpp +93 -0
- data/vendor/faiss/faiss/impl/PdxLayout.h +41 -0
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +62 -37
- data/vendor/faiss/faiss/impl/PolysemousTraining.h +3 -3
- data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +35 -35
- data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +21 -16
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +99 -80
- data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +135 -37
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +148 -21
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +298 -301
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +3 -10
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +15 -41
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +0 -4
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +40 -32
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
- data/vendor/faiss/faiss/impl/ResultHandler.h +218 -113
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +119 -2362
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +27 -3
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +42 -0
- data/vendor/faiss/faiss/impl/VisitedTable.h +76 -0
- data/vendor/faiss/faiss/impl/approx_topk/approx_topk.h +276 -0
- data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +68 -0
- data/vendor/faiss/faiss/{utils → impl}/approx_topk/generic.h +15 -8
- data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +68 -0
- data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab-inl.h +169 -0
- data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab.h +117 -0
- data/vendor/faiss/faiss/impl/approx_topk/simdlib256-inl.h +146 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h +73 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +270 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +460 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h +159 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexPQ_impl.h +92 -0
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +26 -0
- data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +26 -0
- data/vendor/faiss/faiss/impl/binary_hamming/dispatch.h +143 -0
- data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +26 -0
- data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +26 -0
- data/vendor/faiss/faiss/impl/expanded_scanners.h +163 -0
- data/vendor/faiss/faiss/impl/{FastScanDistancePostProcessing.h → fast_scan/FastScanDistancePostProcessing.h} +13 -6
- data/vendor/faiss/faiss/impl/{LookupTableScaler.h → fast_scan/LookupTableScaler.h} +16 -5
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +237 -0
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +185 -0
- data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +229 -0
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +268 -0
- data/vendor/faiss/faiss/impl/{pq4_fast_scan.cpp → fast_scan/fast_scan.cpp} +176 -4
- data/vendor/faiss/faiss/impl/fast_scan/fast_scan.h +341 -0
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +36 -0
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +40 -0
- data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +120 -0
- data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +104 -0
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +213 -0
- data/vendor/faiss/faiss/impl/{pq4_fast_scan_search_qbs.cpp → fast_scan/kernels_simd512.h} +26 -348
- data/vendor/faiss/faiss/impl/fast_scan/rabitq_dispatching.h +90 -0
- data/vendor/faiss/faiss/impl/fast_scan/rabitq_result_handler.h +108 -0
- data/vendor/faiss/faiss/impl/{simd_result_handlers.h → fast_scan/simd_result_handlers.h} +290 -142
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +54 -0
- data/vendor/faiss/faiss/impl/hnsw/LockVector.h +64 -0
- data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +91 -0
- data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -0
- data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +104 -0
- data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +111 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +1950 -505
- data/vendor/faiss/faiss/impl/index_read_utils.h +1 -2
- data/vendor/faiss/faiss/impl/index_write.cpp +112 -21
- data/vendor/faiss/faiss/impl/io.cpp +6 -6
- data/vendor/faiss/faiss/impl/io_macros.h +33 -16
- data/vendor/faiss/faiss/impl/kmeans1d.cpp +10 -10
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +81 -40
- data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
- data/vendor/faiss/faiss/impl/mapped_io.cpp +15 -8
- data/vendor/faiss/faiss/impl/platform_macros.h +11 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +549 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +245 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h +105 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +106 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +21 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +21 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +21 -0
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx2.h → pq_code_distance/pq_code_distance-avx2.h} +43 -220
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx512.h → pq_code_distance/pq_code_distance-avx512.h} +25 -112
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +59 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +96 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +256 -0
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-sve.h → pq_code_distance/pq_code_distance-sve.cpp} +57 -146
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +68 -0
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +320 -483
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
- data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +121 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +137 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +371 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +190 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +94 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +603 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +597 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +388 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +630 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +311 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +387 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +54 -0
- data/vendor/faiss/faiss/impl/simd_dispatch.h +173 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
- data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +274 -171
- data/vendor/faiss/faiss/impl/simdlib/simdlib_avx512.h +414 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +44 -0
- data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_emulated.h +231 -166
- data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_neon.h +275 -217
- data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_ppc64.h +201 -160
- data/vendor/faiss/faiss/impl/svs_io.cpp +12 -3
- data/vendor/faiss/faiss/impl/svs_io.h +8 -2
- data/vendor/faiss/faiss/index_factory.cpp +115 -28
- data/vendor/faiss/faiss/index_io.h +53 -3
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +73 -20
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +24 -14
- data/vendor/faiss/faiss/invlists/DirectMap.h +4 -3
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +157 -73
- data/vendor/faiss/faiss/invlists/InvertedLists.h +86 -23
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +4 -4
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +14 -14
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +9 -19
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +2 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +350 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.h +128 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.cpp +40 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.h +43 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +225 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.h +71 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +25 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +19 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +19 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +14 -0
- data/vendor/faiss/faiss/utils/Heap.cpp +56 -10
- data/vendor/faiss/faiss/utils/Heap.h +21 -0
- data/vendor/faiss/faiss/utils/NeuralNet.cpp +54 -40
- data/vendor/faiss/faiss/utils/NeuralNet.h +1 -1
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +10 -4
- data/vendor/faiss/faiss/utils/distances.cpp +507 -559
- data/vendor/faiss/faiss/utils/distances.h +118 -1
- data/vendor/faiss/faiss/utils/distances_dispatch.h +250 -0
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +8 -7
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +33 -14
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +12 -1
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +16 -293
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +57 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +290 -0
- data/vendor/faiss/faiss/utils/distances_simd.cpp +72 -3681
- data/vendor/faiss/faiss/utils/extra_distances.cpp +60 -102
- data/vendor/faiss/faiss/utils/extra_distances.h +79 -7
- data/vendor/faiss/faiss/utils/hamming-inl.h +13 -11
- data/vendor/faiss/faiss/utils/hamming.cpp +66 -517
- data/vendor/faiss/faiss/utils/hamming.h +92 -2
- data/vendor/faiss/faiss/utils/hamming_distance/common.h +287 -10
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +15 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +15 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx2.h +142 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +234 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-generic.h +368 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +322 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-rvv.h +39 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer.h +146 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +481 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +15 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +15 -0
- data/vendor/faiss/faiss/utils/partitioning.cpp +66 -987
- data/vendor/faiss/faiss/utils/partitioning.h +31 -0
- data/vendor/faiss/faiss/utils/popcount.h +29 -0
- data/vendor/faiss/faiss/utils/pq_code_distance.h +251 -0
- data/vendor/faiss/faiss/utils/prefetch.h +2 -2
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +30 -30
- data/vendor/faiss/faiss/utils/quantize_lut.h +1 -1
- data/vendor/faiss/faiss/utils/rabitq_simd.h +124 -343
- data/vendor/faiss/faiss/utils/random.cpp +6 -6
- data/vendor/faiss/faiss/utils/simd_impl/IVFFlatScanner-inl.h +51 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +154 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +777 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +306 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +1431 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +1095 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +189 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_simdlib256.h +195 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_sse-inl.h +392 -0
- data/vendor/faiss/faiss/utils/{distances_fused/simdlib_based.h → simd_impl/exhaustive_L2sqr_blas_cmax.h} +5 -10
- data/vendor/faiss/faiss/utils/simd_impl/hamming_impl.h +481 -0
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +14 -0
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +14 -0
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +1085 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +355 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +477 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +55 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +55 -0
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +32 -0
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +43 -0
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +57 -0
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +45 -0
- data/vendor/faiss/faiss/utils/simd_levels.cpp +334 -0
- data/vendor/faiss/faiss/utils/simd_levels.h +183 -0
- data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
- data/vendor/faiss/faiss/utils/utils.cpp +21 -14
- data/vendor/faiss/faiss/utils/utils.h +3 -3
- metadata +156 -42
- data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
- data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
- data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +0 -81
- data/vendor/faiss/faiss/impl/code_distance/code_distance.h +0 -186
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -216
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -224
- data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +0 -84
- data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +0 -196
- data/vendor/faiss/faiss/utils/approx_topk/mode.h +0 -34
- data/vendor/faiss/faiss/utils/distances_fused/avx512.h +0 -36
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +0 -228
- data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +0 -462
- data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +0 -490
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -450
- data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +0 -87
- data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +0 -524
- data/vendor/faiss/faiss/utils/simdlib.h +0 -42
- data/vendor/faiss/faiss/utils/simdlib_avx512.h +0 -296
- /data/vendor/faiss/faiss/{cppcontrib/factory_tools.h → factory_tools.h} +0 -0
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
#include <faiss/IndexFlat.h>
|
|
20
20
|
#include <faiss/VectorTransform.h>
|
|
21
21
|
#include <faiss/impl/FaissAssert.h>
|
|
22
|
+
#include <faiss/impl/simd_dispatch.h>
|
|
22
23
|
#include <faiss/utils/distances.h>
|
|
23
24
|
|
|
24
25
|
extern "C" {
|
|
@@ -47,8 +48,8 @@ namespace faiss {
|
|
|
47
48
|
* PQ implementation
|
|
48
49
|
*********************************************/
|
|
49
50
|
|
|
50
|
-
ProductQuantizer::ProductQuantizer(size_t
|
|
51
|
-
: Quantizer(
|
|
51
|
+
ProductQuantizer::ProductQuantizer(size_t d_in, size_t M_in, size_t nbits_in)
|
|
52
|
+
: Quantizer(d_in, 0), M(M_in), nbits(nbits_in), assign_index(nullptr) {
|
|
52
53
|
set_derived_values();
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -56,14 +57,15 @@ ProductQuantizer::ProductQuantizer() : ProductQuantizer(0, 1, 0) {}
|
|
|
56
57
|
|
|
57
58
|
void ProductQuantizer::set_derived_values() {
|
|
58
59
|
// quite a few derived values
|
|
60
|
+
FAISS_THROW_IF_NOT_MSG(M > 0, "M must be > 0");
|
|
59
61
|
FAISS_THROW_IF_NOT_MSG(
|
|
60
62
|
d % M == 0,
|
|
61
63
|
"The dimension of the vector (d) should be a multiple of the number of subquantizers (M)");
|
|
62
64
|
dsub = d / M;
|
|
63
|
-
code_size = (nbits * M + 7) / 8;
|
|
64
65
|
FAISS_THROW_IF_MSG(nbits > 24, "nbits larger than 24 is not practical.");
|
|
66
|
+
code_size = (nbits * M + 7) / 8;
|
|
65
67
|
ksub = 1 << nbits;
|
|
66
|
-
centroids.resize(d
|
|
68
|
+
centroids.resize(mul_no_overflow(d, (size_t)ksub, "PQ centroids"));
|
|
67
69
|
verbose = false;
|
|
68
70
|
train_type = Train_default;
|
|
69
71
|
}
|
|
@@ -137,8 +139,8 @@ void ProductQuantizer::train(size_t n, const float* x) {
|
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
std::unique_ptr<float[]> xslice(new float[n * dsub]);
|
|
140
|
-
for (
|
|
141
|
-
for (
|
|
142
|
+
for (size_t m = 0; m < M; m++) {
|
|
143
|
+
for (size_t j = 0; j < n; j++)
|
|
142
144
|
memcpy(xslice.get() + j * dsub,
|
|
143
145
|
x + j * d + m * dsub,
|
|
144
146
|
dsub * sizeof(float));
|
|
@@ -177,7 +179,7 @@ void ProductQuantizer::train(size_t n, const float* x) {
|
|
|
177
179
|
|
|
178
180
|
if (verbose) {
|
|
179
181
|
clus.verbose = true;
|
|
180
|
-
printf("Training PQ slice %
|
|
182
|
+
printf("Training PQ slice %zd/%zd\n", m, M);
|
|
181
183
|
}
|
|
182
184
|
IndexFlatL2 index(dsub);
|
|
183
185
|
clus.train(n, xslice.get(), assign_index ? *assign_index : index);
|
|
@@ -195,14 +197,16 @@ void ProductQuantizer::train(size_t n, const float* x) {
|
|
|
195
197
|
IndexFlatL2 index(dsub);
|
|
196
198
|
|
|
197
199
|
clus.train(n * M, x, assign_index ? *assign_index : index);
|
|
198
|
-
for (
|
|
200
|
+
for (size_t m = 0; m < M; m++) {
|
|
199
201
|
set_params(clus.centroids.data(), m);
|
|
200
202
|
}
|
|
201
203
|
}
|
|
202
204
|
}
|
|
203
205
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
namespace {
|
|
207
|
+
|
|
208
|
+
template <class PQEncoder, SIMDLevel SL>
|
|
209
|
+
void compute_1_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
|
|
206
210
|
std::vector<float> distances(pq.ksub);
|
|
207
211
|
|
|
208
212
|
// It seems to be meaningless to allocate std::vector<float> distances.
|
|
@@ -248,7 +252,7 @@ void compute_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
|
|
|
248
252
|
uint64_t idxm = 0;
|
|
249
253
|
if (pq.transposed_centroids.empty()) {
|
|
250
254
|
// the regular version
|
|
251
|
-
idxm = fvec_L2sqr_ny_nearest(
|
|
255
|
+
idxm = fvec_L2sqr_ny_nearest<SL>(
|
|
252
256
|
distances.data(),
|
|
253
257
|
xsub,
|
|
254
258
|
pq.get_centroids(m, 0),
|
|
@@ -256,7 +260,7 @@ void compute_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
|
|
|
256
260
|
pq.ksub);
|
|
257
261
|
} else {
|
|
258
262
|
// transposed centroids are available, use'em
|
|
259
|
-
idxm = fvec_L2sqr_ny_nearest_y_transposed(
|
|
263
|
+
idxm = fvec_L2sqr_ny_nearest_y_transposed<SL>(
|
|
260
264
|
distances.data(),
|
|
261
265
|
xsub,
|
|
262
266
|
pq.transposed_centroids.data() + m * pq.ksub,
|
|
@@ -270,20 +274,24 @@ void compute_code(const ProductQuantizer& pq, const float* x, uint8_t* code) {
|
|
|
270
274
|
}
|
|
271
275
|
}
|
|
272
276
|
|
|
277
|
+
} // namespace
|
|
278
|
+
|
|
273
279
|
void ProductQuantizer::compute_code(const float* x, uint8_t* code) const {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
280
|
+
with_simd_level([&]<SIMDLevel SL>() {
|
|
281
|
+
switch (nbits) {
|
|
282
|
+
case 8:
|
|
283
|
+
compute_1_code<PQEncoder8, SL>(*this, x, code);
|
|
284
|
+
break;
|
|
278
285
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
286
|
+
case 16:
|
|
287
|
+
compute_1_code<PQEncoder16, SL>(*this, x, code);
|
|
288
|
+
break;
|
|
282
289
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
290
|
+
default:
|
|
291
|
+
compute_1_code<PQEncoderGeneric, SL>(*this, x, code);
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
}); // with_simd_level
|
|
287
295
|
}
|
|
288
296
|
|
|
289
297
|
template <class PQDecoder>
|
|
@@ -314,8 +322,9 @@ void ProductQuantizer::decode(const uint8_t* code, float* x) const {
|
|
|
314
322
|
}
|
|
315
323
|
|
|
316
324
|
void ProductQuantizer::decode(const uint8_t* code, float* x, size_t n) const {
|
|
325
|
+
int64_t n_signed = n;
|
|
317
326
|
#pragma omp parallel for if (n > 100)
|
|
318
|
-
for (int64_t i = 0; i <
|
|
327
|
+
for (int64_t i = 0; i < n_signed; i++) {
|
|
319
328
|
this->decode(code + code_size * i, x + d * i);
|
|
320
329
|
}
|
|
321
330
|
}
|
|
@@ -345,7 +354,8 @@ void ProductQuantizer::compute_codes_with_assign_index(
|
|
|
345
354
|
const float* x,
|
|
346
355
|
uint8_t* codes,
|
|
347
356
|
size_t n) {
|
|
348
|
-
FAISS_THROW_IF_NOT(
|
|
357
|
+
FAISS_THROW_IF_NOT(
|
|
358
|
+
assign_index && static_cast<size_t>(assign_index->d) == dsub);
|
|
349
359
|
|
|
350
360
|
for (size_t m = 0; m < M; m++) {
|
|
351
361
|
assign_index->reset();
|
|
@@ -407,10 +417,11 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
|
|
|
407
417
|
return;
|
|
408
418
|
}
|
|
409
419
|
|
|
420
|
+
int64_t n_signed = n;
|
|
410
421
|
if (dsub < 16) { // simple direct computation
|
|
411
422
|
|
|
412
423
|
#pragma omp parallel for
|
|
413
|
-
for (int64_t i = 0; i <
|
|
424
|
+
for (int64_t i = 0; i < n_signed; i++)
|
|
414
425
|
compute_code(x + i * d, codes + i * code_size);
|
|
415
426
|
|
|
416
427
|
} else { // worthwhile to use BLAS
|
|
@@ -418,7 +429,7 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
|
|
|
418
429
|
compute_distance_tables(n, x, dis_tables.get());
|
|
419
430
|
|
|
420
431
|
#pragma omp parallel for
|
|
421
|
-
for (int64_t i = 0; i <
|
|
432
|
+
for (int64_t i = 0; i < n_signed; i++) {
|
|
422
433
|
uint8_t* code = codes + i * code_size;
|
|
423
434
|
const float* tab = dis_tables.get() + i * ksub * M;
|
|
424
435
|
compute_code_from_distance_table(tab, code);
|
|
@@ -428,51 +439,54 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
|
|
|
428
439
|
|
|
429
440
|
void ProductQuantizer::compute_distance_table(const float* x, float* dis_table)
|
|
430
441
|
const {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
442
|
+
with_simd_level([&]<SIMDLevel SL>() {
|
|
443
|
+
if (transposed_centroids.empty()) {
|
|
444
|
+
// use regular version
|
|
445
|
+
for (size_t m = 0; m < M; m++) {
|
|
446
|
+
fvec_L2sqr_ny<SL>(
|
|
447
|
+
dis_table + m * ksub,
|
|
448
|
+
x + m * dsub,
|
|
449
|
+
get_centroids(m, 0),
|
|
450
|
+
dsub,
|
|
451
|
+
ksub);
|
|
452
|
+
}
|
|
453
|
+
} else {
|
|
454
|
+
// transposed centroids are available, use'em
|
|
455
|
+
for (size_t m = 0; m < M; m++) {
|
|
456
|
+
fvec_L2sqr_ny_transposed<SL>(
|
|
457
|
+
dis_table + m * ksub,
|
|
458
|
+
x + m * dsub,
|
|
459
|
+
transposed_centroids.data() + m * ksub,
|
|
460
|
+
centroids_sq_lengths.data() + m * ksub,
|
|
461
|
+
dsub,
|
|
462
|
+
M * ksub,
|
|
463
|
+
ksub);
|
|
464
|
+
}
|
|
440
465
|
}
|
|
441
|
-
}
|
|
442
|
-
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
void ProductQuantizer::compute_inner_prod_table(
|
|
470
|
+
const float* x,
|
|
471
|
+
float* dis_table) const {
|
|
472
|
+
with_simd_level([&]<SIMDLevel SL>() {
|
|
443
473
|
for (size_t m = 0; m < M; m++) {
|
|
444
|
-
|
|
474
|
+
fvec_inner_products_ny<SL>(
|
|
445
475
|
dis_table + m * ksub,
|
|
446
476
|
x + m * dsub,
|
|
447
|
-
|
|
448
|
-
centroids_sq_lengths.data() + m * ksub,
|
|
477
|
+
get_centroids(m, 0),
|
|
449
478
|
dsub,
|
|
450
|
-
M * ksub,
|
|
451
479
|
ksub);
|
|
452
480
|
}
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
void ProductQuantizer::compute_inner_prod_table(
|
|
457
|
-
const float* x,
|
|
458
|
-
float* dis_table) const {
|
|
459
|
-
size_t m;
|
|
460
|
-
|
|
461
|
-
for (m = 0; m < M; m++) {
|
|
462
|
-
fvec_inner_products_ny(
|
|
463
|
-
dis_table + m * ksub,
|
|
464
|
-
x + m * dsub,
|
|
465
|
-
get_centroids(m, 0),
|
|
466
|
-
dsub,
|
|
467
|
-
ksub);
|
|
468
|
-
}
|
|
481
|
+
});
|
|
469
482
|
}
|
|
470
483
|
|
|
471
484
|
void ProductQuantizer::compute_distance_tables(
|
|
472
485
|
size_t nx,
|
|
473
486
|
const float* x,
|
|
474
487
|
float* dis_tables) const {
|
|
475
|
-
|
|
488
|
+
int64_t nx_signed = nx;
|
|
489
|
+
#if defined(COMPILE_SIMD_AVX2) || defined(COMPILE_SIMD_ARM_NEON)
|
|
476
490
|
if (dsub == 2 && nbits < 8) { // interesting for a narrow range of settings
|
|
477
491
|
compute_PQ_dis_tables_dsub2(
|
|
478
492
|
d, ksub, centroids.data(), nx, x, false, dis_tables);
|
|
@@ -481,13 +495,13 @@ void ProductQuantizer::compute_distance_tables(
|
|
|
481
495
|
if (dsub < 16) {
|
|
482
496
|
|
|
483
497
|
#pragma omp parallel for if (nx > 1)
|
|
484
|
-
for (int64_t i = 0; i <
|
|
498
|
+
for (int64_t i = 0; i < nx_signed; i++) {
|
|
485
499
|
compute_distance_table(x + i * d, dis_tables + i * ksub * M);
|
|
486
500
|
}
|
|
487
501
|
|
|
488
502
|
} else { // use BLAS
|
|
489
503
|
|
|
490
|
-
for (
|
|
504
|
+
for (size_t m = 0; m < M; m++) {
|
|
491
505
|
pairwise_L2sqr(
|
|
492
506
|
dsub,
|
|
493
507
|
nx,
|
|
@@ -506,7 +520,8 @@ void ProductQuantizer::compute_inner_prod_tables(
|
|
|
506
520
|
size_t nx,
|
|
507
521
|
const float* x,
|
|
508
522
|
float* dis_tables) const {
|
|
509
|
-
|
|
523
|
+
int64_t nx_signed = nx;
|
|
524
|
+
#if defined(COMPILE_SIMD_AVX2) || defined(COMPILE_SIMD_ARM_NEON)
|
|
510
525
|
if (dsub == 2 && nbits < 8) {
|
|
511
526
|
compute_PQ_dis_tables_dsub2(
|
|
512
527
|
d, ksub, centroids.data(), nx, x, true, dis_tables);
|
|
@@ -515,14 +530,14 @@ void ProductQuantizer::compute_inner_prod_tables(
|
|
|
515
530
|
if (dsub < 16) {
|
|
516
531
|
|
|
517
532
|
#pragma omp parallel for if (nx > 1)
|
|
518
|
-
for (int64_t i = 0; i <
|
|
533
|
+
for (int64_t i = 0; i < nx_signed; i++) {
|
|
519
534
|
compute_inner_prod_table(x + i * d, dis_tables + i * ksub * M);
|
|
520
535
|
}
|
|
521
536
|
|
|
522
537
|
} else { // use BLAS
|
|
523
538
|
|
|
524
539
|
// compute distance tables
|
|
525
|
-
for (
|
|
540
|
+
for (size_t m = 0; m < M; m++) {
|
|
526
541
|
FINTEGER ldc = ksub * M, nxi = nx, ksubi = ksub, dsubi = dsub,
|
|
527
542
|
di = d;
|
|
528
543
|
float one = 1.0, zero = 0;
|
|
@@ -566,7 +581,7 @@ void pq_estimators_from_tables_Mmul4(
|
|
|
566
581
|
float dis = 0;
|
|
567
582
|
const float* dt = dis_table;
|
|
568
583
|
|
|
569
|
-
for (
|
|
584
|
+
for (int m = 0; m < M; m += 4) {
|
|
570
585
|
float dism = 0;
|
|
571
586
|
dism = dt[*codes++];
|
|
572
587
|
dt += ksub;
|
|
@@ -638,7 +653,7 @@ void pq_estimators_from_tables(
|
|
|
638
653
|
for (size_t j = 0; j < ncodes; j++) {
|
|
639
654
|
float dis = 0;
|
|
640
655
|
const float* __restrict dt = dis_table;
|
|
641
|
-
for (
|
|
656
|
+
for (size_t m = 0; m < M; m++) {
|
|
642
657
|
dis += dt[*codes++];
|
|
643
658
|
dt += ksub;
|
|
644
659
|
}
|
|
@@ -686,10 +701,11 @@ void pq_knn_search_with_tables(
|
|
|
686
701
|
HeapArray<C>* res,
|
|
687
702
|
bool init_finalize_heap) {
|
|
688
703
|
size_t k = res->k, nx = res->nh;
|
|
704
|
+
int64_t nx_signed = nx;
|
|
689
705
|
size_t ksub = pq.ksub, M = pq.M;
|
|
690
706
|
|
|
691
707
|
#pragma omp parallel for if (nx > 1)
|
|
692
|
-
for (int64_t i = 0; i <
|
|
708
|
+
for (int64_t i = 0; i < nx_signed; i++) {
|
|
693
709
|
/* query preparation for asymmetric search: compute look-up tables */
|
|
694
710
|
const float* dis_table = dis_tables + i * ksub * M;
|
|
695
711
|
|
|
@@ -785,22 +801,24 @@ void ProductQuantizer::compute_sdc_table() {
|
|
|
785
801
|
sdc_table.resize(M * ksub * ksub);
|
|
786
802
|
|
|
787
803
|
if (dsub < 4) {
|
|
804
|
+
with_simd_level([&]<SIMDLevel SL>() {
|
|
788
805
|
#pragma omp parallel for
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
806
|
+
for (int64_t mk = 0; mk < static_cast<int64_t>(M * ksub); mk++) {
|
|
807
|
+
// allow omp to schedule in a more fine-grained way
|
|
808
|
+
// `collapse` is not supported in OpenMP 2.x
|
|
809
|
+
int m = mk / ksub;
|
|
810
|
+
int k = mk % ksub;
|
|
811
|
+
const float* cents = centroids.data() + m * ksub * dsub;
|
|
812
|
+
const float* centi = cents + k * dsub;
|
|
813
|
+
float* dis_tab = sdc_table.data() + m * ksub * ksub;
|
|
814
|
+
fvec_L2sqr_ny<SL>(dis_tab + k * ksub, centi, cents, dsub, ksub);
|
|
815
|
+
}
|
|
816
|
+
});
|
|
799
817
|
} else {
|
|
800
818
|
// NOTE: it would disable the omp loop in pairwise_L2sqr
|
|
801
819
|
// but still accelerate especially when M >= 4
|
|
802
820
|
#pragma omp parallel for
|
|
803
|
-
for (
|
|
821
|
+
for (int64_t m = 0; m < static_cast<int64_t>(M); m++) {
|
|
804
822
|
const float* cents = centroids.data() + m * ksub * dsub;
|
|
805
823
|
float* dis_tab = sdc_table.data() + m * ksub * ksub;
|
|
806
824
|
pairwise_L2sqr(
|
|
@@ -819,9 +837,10 @@ void ProductQuantizer::search_sdc(
|
|
|
819
837
|
FAISS_THROW_IF_NOT(sdc_table.size() == M * ksub * ksub);
|
|
820
838
|
FAISS_THROW_IF_NOT(nbits == 8);
|
|
821
839
|
size_t k = res->k;
|
|
840
|
+
int64_t nq_signed = nq;
|
|
822
841
|
|
|
823
842
|
#pragma omp parallel for
|
|
824
|
-
for (int64_t i = 0; i <
|
|
843
|
+
for (int64_t i = 0; i < nq_signed; i++) {
|
|
825
844
|
/* Compute distances and keep smallest values */
|
|
826
845
|
idx_t* heap_ids = res->ids + i * k;
|
|
827
846
|
float* heap_dis = res->val + i * k;
|
|
@@ -834,7 +853,7 @@ void ProductQuantizer::search_sdc(
|
|
|
834
853
|
for (size_t j = 0; j < nb; j++) {
|
|
835
854
|
float dis = 0;
|
|
836
855
|
const float* tab = sdc_table.data();
|
|
837
|
-
for (
|
|
856
|
+
for (size_t m = 0; m < M; m++) {
|
|
838
857
|
dis += tab[bcode[m] + qcode[m] * ksub];
|
|
839
858
|
tab += ksub * ksub;
|
|
840
859
|
}
|
|
@@ -16,8 +16,8 @@ struct Quantizer {
|
|
|
16
16
|
size_t d; ///< size of the input vectors
|
|
17
17
|
size_t code_size; ///< bytes per indexed vector
|
|
18
18
|
|
|
19
|
-
explicit Quantizer(size_t
|
|
20
|
-
: d(
|
|
19
|
+
explicit Quantizer(size_t d_in = 0, size_t code_size_in = 0)
|
|
20
|
+
: d(d_in), code_size(code_size_in) {}
|
|
21
21
|
|
|
22
22
|
/** Train the quantizer
|
|
23
23
|
*
|
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
#include <faiss/impl/RaBitQUtils.h>
|
|
9
9
|
|
|
10
10
|
#include <faiss/impl/FaissAssert.h>
|
|
11
|
+
#include <faiss/impl/simd_dispatch.h>
|
|
11
12
|
#include <faiss/utils/distances.h>
|
|
13
|
+
#include <faiss/utils/rabitq_simd.h>
|
|
12
14
|
#include <algorithm>
|
|
13
15
|
#include <cmath>
|
|
16
|
+
#include <cstring>
|
|
14
17
|
#include <limits>
|
|
15
18
|
|
|
16
19
|
namespace faiss {
|
|
@@ -151,6 +154,7 @@ QueryFactorsData compute_query_factors(
|
|
|
151
154
|
std::vector<uint8_t>& rotated_qq) {
|
|
152
155
|
FAISS_THROW_IF_NOT(qb <= 8);
|
|
153
156
|
FAISS_THROW_IF_NOT(qb > 0);
|
|
157
|
+
FAISS_THROW_IF_NOT(d > 0);
|
|
154
158
|
|
|
155
159
|
QueryFactorsData query_factors;
|
|
156
160
|
|
|
@@ -163,38 +167,42 @@ QueryFactorsData compute_query_factors(
|
|
|
163
167
|
query_factors.g_error = std::sqrt(query_factors.qr_to_c_L2sqr);
|
|
164
168
|
|
|
165
169
|
// Rotate the query (subtract centroid)
|
|
170
|
+
// Save aliasing state before resize(), which may reallocate the buffer.
|
|
171
|
+
const bool query_aliased = (query == rotated_q.data());
|
|
172
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
173
|
+
!query_aliased || centroid == nullptr,
|
|
174
|
+
"query aliasing is only supported in the IVF residual path "
|
|
175
|
+
"(centroid == nullptr)");
|
|
166
176
|
rotated_q.resize(d);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
177
|
+
if (centroid == nullptr) {
|
|
178
|
+
// Caller may pass query == rotated_q.data() (IVF residual path);
|
|
179
|
+
// memcpy with overlapping src/dst is UB, so skip the copy in that case.
|
|
180
|
+
if (!query_aliased) {
|
|
181
|
+
memcpy(rotated_q.data(), query, d * sizeof(float));
|
|
182
|
+
}
|
|
183
|
+
} else {
|
|
184
|
+
for (size_t i = 0; i < d; i++) {
|
|
185
|
+
rotated_q[i] = query[i] - centroid[i];
|
|
171
186
|
}
|
|
172
187
|
}
|
|
173
188
|
|
|
174
|
-
const float inv_d_sqrt =
|
|
175
|
-
(d == 0) ? 1.0f : (1.0f / std::sqrt(static_cast<float>(d)));
|
|
189
|
+
const float inv_d_sqrt = 1.0f / std::sqrt(static_cast<float>(d));
|
|
176
190
|
|
|
177
191
|
// Compute quantization range
|
|
178
192
|
float v_min = std::numeric_limits<float>::max();
|
|
179
193
|
float v_max = std::numeric_limits<float>::lowest();
|
|
180
194
|
|
|
195
|
+
const float* rq = rotated_q.data();
|
|
181
196
|
if (centered) {
|
|
182
197
|
float z_max = Z_MAX_BY_QB[qb - 1];
|
|
183
198
|
float v_radius = z_max * std::sqrt(query_factors.qr_to_c_L2sqr / d);
|
|
184
199
|
v_min = -v_radius;
|
|
185
200
|
v_max = v_radius;
|
|
186
201
|
} else {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
v_min = std::min(v_min, v_q);
|
|
192
|
-
v_max = std::max(v_max, v_q);
|
|
193
|
-
}
|
|
194
|
-
} else {
|
|
195
|
-
// For empty dimensions, use default range
|
|
196
|
-
v_min = 0.0f;
|
|
197
|
-
v_max = 1.0f;
|
|
202
|
+
for (size_t i = 0; i < d; i++) {
|
|
203
|
+
const float v_q = rq[i];
|
|
204
|
+
v_min = std::min(v_min, v_q);
|
|
205
|
+
v_max = std::max(v_max, v_q);
|
|
198
206
|
}
|
|
199
207
|
}
|
|
200
208
|
|
|
@@ -207,25 +215,18 @@ QueryFactorsData compute_query_factors(
|
|
|
207
215
|
size_t sum_qq = 0;
|
|
208
216
|
int64_t sum2_signed_odd_int = 0;
|
|
209
217
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
int64_t signed_odd_int = int64_t(v_qq) * 2 - max_code;
|
|
222
|
-
sum2_signed_odd_int += signed_odd_int * signed_odd_int;
|
|
223
|
-
}
|
|
218
|
+
uint8_t* rqq = rotated_qq.data();
|
|
219
|
+
for (size_t i = 0; i < d; i++) {
|
|
220
|
+
const float v_q = rq[i];
|
|
221
|
+
const uint8_t v_qq = std::clamp<float>(
|
|
222
|
+
std::round((v_q - v_min) * inv_delta), 0, max_code);
|
|
223
|
+
rqq[i] = v_qq;
|
|
224
|
+
sum_qq += v_qq;
|
|
225
|
+
|
|
226
|
+
if (centered) {
|
|
227
|
+
int64_t signed_odd_int = int64_t(v_qq) * 2 - max_code;
|
|
228
|
+
sum2_signed_odd_int += signed_odd_int * signed_odd_int;
|
|
224
229
|
}
|
|
225
|
-
} else {
|
|
226
|
-
FAISS_THROW_MSG(
|
|
227
|
-
"Arrays unexpectedly empty when d=" + std::to_string(d) +
|
|
228
|
-
"or d is incorrectly set");
|
|
229
230
|
}
|
|
230
231
|
|
|
231
232
|
// Compute query factors
|
|
@@ -240,10 +241,18 @@ QueryFactorsData compute_query_factors(
|
|
|
240
241
|
query_factors.int_dot_scale = 1.0f;
|
|
241
242
|
}
|
|
242
243
|
|
|
243
|
-
// Compute query norm for inner product metric
|
|
244
|
+
// Compute query norm for inner product metric.
|
|
245
|
+
// When centroid is nullptr (IVF residual path), qr_to_c_L2sqr already
|
|
246
|
+
// holds fvec_norm_L2sqr(query, d) from line 164, so reuse it.
|
|
244
247
|
query_factors.qr_norm_L2sqr = 0.0f;
|
|
248
|
+
query_factors.q_dot_c = 0.0f;
|
|
245
249
|
if (metric_type == MetricType::METRIC_INNER_PRODUCT) {
|
|
246
|
-
query_factors.qr_norm_L2sqr =
|
|
250
|
+
query_factors.qr_norm_L2sqr = (centroid == nullptr)
|
|
251
|
+
? query_factors.qr_to_c_L2sqr
|
|
252
|
+
: fvec_norm_L2sqr(query, d);
|
|
253
|
+
if (centroid != nullptr) {
|
|
254
|
+
query_factors.q_dot_c = fvec_inner_product(query, centroid, d);
|
|
255
|
+
}
|
|
247
256
|
}
|
|
248
257
|
|
|
249
258
|
return query_factors;
|
|
@@ -290,5 +299,94 @@ void set_bit_fastscan(uint8_t* code, size_t bit_index) {
|
|
|
290
299
|
}
|
|
291
300
|
}
|
|
292
301
|
|
|
302
|
+
size_t compute_per_vector_storage_size(size_t nb_bits, size_t d) {
|
|
303
|
+
const size_t ex_bits = nb_bits - 1;
|
|
304
|
+
if (ex_bits == 0) {
|
|
305
|
+
return sizeof(SignBitFactors);
|
|
306
|
+
} else {
|
|
307
|
+
return sizeof(SignBitFactorsWithError) + sizeof(ExtraBitsFactors) +
|
|
308
|
+
(d * ex_bits + 7) / 8;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Non-template wrapper with dynamic dispatch (one dispatch per call).
|
|
313
|
+
// The hot path in RaBitQuantizer dispatches once at distance computer
|
|
314
|
+
// construction, so per-vector dispatch only affects this utility path.
|
|
315
|
+
float compute_full_multibit_distance(
|
|
316
|
+
const uint8_t* sign_bits,
|
|
317
|
+
const uint8_t* ex_code,
|
|
318
|
+
const ExtraBitsFactors& ex_fac,
|
|
319
|
+
const float* rotated_q,
|
|
320
|
+
float qr_base,
|
|
321
|
+
size_t d,
|
|
322
|
+
size_t ex_bits,
|
|
323
|
+
MetricType metric_type) {
|
|
324
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_A0>(
|
|
325
|
+
[&]<SIMDLevel SL>() {
|
|
326
|
+
return compute_full_multibit_distance<SL>(
|
|
327
|
+
sign_bits,
|
|
328
|
+
ex_code,
|
|
329
|
+
ex_fac,
|
|
330
|
+
rotated_q,
|
|
331
|
+
qr_base,
|
|
332
|
+
d,
|
|
333
|
+
ex_bits,
|
|
334
|
+
metric_type);
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
void populate_block_aux_from_flat_storage(
|
|
339
|
+
const std::vector<uint8_t>& flat_storage,
|
|
340
|
+
AlignedTable<uint8_t>& codes,
|
|
341
|
+
size_t num_vectors,
|
|
342
|
+
size_t bbs,
|
|
343
|
+
size_t M2,
|
|
344
|
+
size_t old_block_stride,
|
|
345
|
+
size_t new_block_stride,
|
|
346
|
+
size_t storage_size,
|
|
347
|
+
const int64_t* id_map) {
|
|
348
|
+
if (flat_storage.empty() || num_vectors == 0) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const size_t packed_block_size = ((M2 + 1) / 2) * bbs;
|
|
353
|
+
const size_t n_blocks = (num_vectors + bbs - 1) / bbs;
|
|
354
|
+
|
|
355
|
+
if (old_block_stride < new_block_stride) {
|
|
356
|
+
AlignedTable<uint8_t> old_data;
|
|
357
|
+
old_data.resize(codes.size());
|
|
358
|
+
memcpy(old_data.data(), codes.data(), codes.size());
|
|
359
|
+
|
|
360
|
+
codes.resize(n_blocks * new_block_stride);
|
|
361
|
+
memset(codes.data(), 0, n_blocks * new_block_stride);
|
|
362
|
+
for (size_t b = 0; b < n_blocks; b++) {
|
|
363
|
+
memcpy(codes.data() + b * new_block_stride,
|
|
364
|
+
old_data.data() + b * old_block_stride,
|
|
365
|
+
packed_block_size);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
for (size_t offset = 0; offset < num_vectors; offset++) {
|
|
370
|
+
const int64_t global_id =
|
|
371
|
+
id_map ? id_map[offset] : static_cast<int64_t>(offset);
|
|
372
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
373
|
+
global_id >= 0 &&
|
|
374
|
+
static_cast<size_t>(global_id) * storage_size +
|
|
375
|
+
storage_size <=
|
|
376
|
+
flat_storage.size(),
|
|
377
|
+
"global_id out of bounds for flat_storage during migration");
|
|
378
|
+
|
|
379
|
+
const uint8_t* src = flat_storage.data() + global_id * storage_size;
|
|
380
|
+
uint8_t* dst = get_block_aux_ptr(
|
|
381
|
+
codes.data(),
|
|
382
|
+
offset,
|
|
383
|
+
bbs,
|
|
384
|
+
packed_block_size,
|
|
385
|
+
new_block_stride,
|
|
386
|
+
storage_size);
|
|
387
|
+
memcpy(dst, src, storage_size);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
293
391
|
} // namespace rabitq_utils
|
|
294
392
|
} // namespace faiss
|