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
|
@@ -29,7 +29,7 @@ struct ZnSphereSearch {
|
|
|
29
29
|
/// size dim * natom
|
|
30
30
|
std::vector<float> voc;
|
|
31
31
|
|
|
32
|
-
ZnSphereSearch(int dim, int
|
|
32
|
+
ZnSphereSearch(int dim, int r2_in);
|
|
33
33
|
|
|
34
34
|
/// find nearest centroid. x does not need to be normalized
|
|
35
35
|
float search(const float* x, float* c) const;
|
|
@@ -57,7 +57,7 @@ struct EnumeratedVectors {
|
|
|
57
57
|
uint64_t nv;
|
|
58
58
|
int dim;
|
|
59
59
|
|
|
60
|
-
explicit EnumeratedVectors(int
|
|
60
|
+
explicit EnumeratedVectors(int dim_in) : nv(0), dim(dim_in) {}
|
|
61
61
|
|
|
62
62
|
/// encode a vector from a collection
|
|
63
63
|
virtual uint64_t encode(const float* x) const = 0;
|
|
@@ -98,7 +98,7 @@ struct Repeats {
|
|
|
98
98
|
std::vector<Repeat> repeats;
|
|
99
99
|
|
|
100
100
|
// initialize from a template of the atom.
|
|
101
|
-
Repeats(int
|
|
101
|
+
Repeats(int dim_in = 0, const float* c = nullptr);
|
|
102
102
|
|
|
103
103
|
// count number of possible codes for this atom
|
|
104
104
|
uint64_t count() const;
|
|
@@ -124,7 +124,7 @@ struct ZnSphereCodec : ZnSphereSearch, EnumeratedVectors {
|
|
|
124
124
|
uint64_t nv;
|
|
125
125
|
size_t code_size;
|
|
126
126
|
|
|
127
|
-
ZnSphereCodec(int
|
|
127
|
+
ZnSphereCodec(int dim_in, int r2_in);
|
|
128
128
|
|
|
129
129
|
uint64_t search_and_encode(const float* x) const;
|
|
130
130
|
|
|
@@ -146,7 +146,7 @@ struct ZnSphereCodecRec : EnumeratedVectors {
|
|
|
146
146
|
int log2_dim;
|
|
147
147
|
int code_size;
|
|
148
148
|
|
|
149
|
-
ZnSphereCodecRec(int
|
|
149
|
+
ZnSphereCodecRec(int dim_in, int r2_in);
|
|
150
150
|
|
|
151
151
|
uint64_t encode_centroid(const float* c) const;
|
|
152
152
|
|
|
@@ -176,7 +176,7 @@ struct ZnSphereCodecAlt : ZnSphereCodec {
|
|
|
176
176
|
bool use_rec;
|
|
177
177
|
ZnSphereCodecRec znc_rec;
|
|
178
178
|
|
|
179
|
-
ZnSphereCodecAlt(int
|
|
179
|
+
ZnSphereCodecAlt(int dim_in, int r2_in);
|
|
180
180
|
|
|
181
181
|
uint64_t encode(const float* x) const override;
|
|
182
182
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#include <stdio.h>
|
|
9
9
|
|
|
10
|
-
#if defined(__linux__) || defined(__FreeBSD__)
|
|
10
|
+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
|
|
11
11
|
|
|
12
12
|
#include <fcntl.h>
|
|
13
13
|
#include <sys/mman.h>
|
|
@@ -27,15 +27,22 @@
|
|
|
27
27
|
|
|
28
28
|
namespace faiss {
|
|
29
29
|
|
|
30
|
-
#if defined(__linux__) || defined(__FreeBSD__)
|
|
30
|
+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
|
|
31
31
|
|
|
32
32
|
struct MmappedFileMappingOwner::PImpl {
|
|
33
33
|
void* ptr = nullptr;
|
|
34
34
|
size_t ptr_size = 0;
|
|
35
35
|
|
|
36
36
|
explicit PImpl(const std::string& filename) {
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
struct FileDeleter {
|
|
38
|
+
void operator()(FILE* f) const {
|
|
39
|
+
if (f)
|
|
40
|
+
fclose(f);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
auto f = std::unique_ptr<FILE, FileDeleter>(
|
|
45
|
+
fopen(filename.c_str(), "r"), FileDeleter{});
|
|
39
46
|
FAISS_THROW_IF_NOT_FMT(
|
|
40
47
|
f.get(),
|
|
41
48
|
"could not open %s for reading: %s",
|
|
@@ -53,11 +60,11 @@ struct MmappedFileMappingOwner::PImpl {
|
|
|
53
60
|
void* address = mmap(
|
|
54
61
|
nullptr, filesize, PROT_READ, MAP_SHARED, fileno(f.get()), 0);
|
|
55
62
|
FAISS_THROW_IF_NOT_FMT(
|
|
56
|
-
address !=
|
|
63
|
+
address != MAP_FAILED, "could not mmap(): %s", strerror(errno));
|
|
57
64
|
|
|
58
65
|
// btw, fd can be closed here
|
|
59
66
|
|
|
60
|
-
madvise(address, filesize, MADV_RANDOM);
|
|
67
|
+
(void)madvise(address, filesize, MADV_RANDOM);
|
|
61
68
|
|
|
62
69
|
// save it
|
|
63
70
|
ptr = address;
|
|
@@ -76,11 +83,11 @@ struct MmappedFileMappingOwner::PImpl {
|
|
|
76
83
|
void* address =
|
|
77
84
|
mmap(nullptr, filesize, PROT_READ, MAP_SHARED, fileno(f), 0);
|
|
78
85
|
FAISS_THROW_IF_NOT_FMT(
|
|
79
|
-
address !=
|
|
86
|
+
address != MAP_FAILED, "could not mmap(): %s", strerror(errno));
|
|
80
87
|
|
|
81
88
|
// btw, fd can be closed here
|
|
82
89
|
|
|
83
|
-
madvise(address, filesize, MADV_RANDOM);
|
|
90
|
+
(void)madvise(address, filesize, MADV_RANDOM);
|
|
84
91
|
|
|
85
92
|
// save it
|
|
86
93
|
ptr = address;
|
|
@@ -74,10 +74,6 @@ inline int __builtin_clzll(uint64_t x) {
|
|
|
74
74
|
}
|
|
75
75
|
#endif
|
|
76
76
|
|
|
77
|
-
#define __builtin_popcount __popcnt
|
|
78
|
-
#define __builtin_popcountl __popcnt64
|
|
79
|
-
#define __builtin_popcountll __popcnt64
|
|
80
|
-
|
|
81
77
|
#ifndef __clang__
|
|
82
78
|
#define __m128i_u __m128i
|
|
83
79
|
#define __m256i_u __m256i
|
|
@@ -110,9 +106,16 @@ inline int __builtin_clzll(uint64_t x) {
|
|
|
110
106
|
// MSVC uses pragma pack instead of __attribute__((packed))
|
|
111
107
|
// Use FAISS_PACK_STRUCTS_BEGIN/END to wrap packed structure definitions
|
|
112
108
|
#define FAISS_PACKED
|
|
109
|
+
#define FAISS_RESTRICT __restrict
|
|
113
110
|
#define FAISS_PACK_STRUCTS_BEGIN __pragma(pack(push, 1))
|
|
114
111
|
#define FAISS_PACK_STRUCTS_END __pragma(pack(pop))
|
|
115
112
|
|
|
113
|
+
#ifdef SWIG
|
|
114
|
+
#define FAISS_MAYBE_UNUSED
|
|
115
|
+
#else
|
|
116
|
+
#define FAISS_MAYBE_UNUSED [[maybe_unused]]
|
|
117
|
+
#endif
|
|
118
|
+
|
|
116
119
|
#else
|
|
117
120
|
/*******************************************************
|
|
118
121
|
* Linux and OSX
|
|
@@ -126,9 +129,13 @@ inline int __builtin_clzll(uint64_t x) {
|
|
|
126
129
|
#ifdef SWIG
|
|
127
130
|
#define ALIGNED(x)
|
|
128
131
|
#define FAISS_PACKED
|
|
132
|
+
#define FAISS_RESTRICT
|
|
133
|
+
#define FAISS_MAYBE_UNUSED
|
|
129
134
|
#else
|
|
130
135
|
#define ALIGNED(x) __attribute__((aligned(x)))
|
|
131
136
|
#define FAISS_PACKED __attribute__((packed))
|
|
137
|
+
#define FAISS_RESTRICT __restrict
|
|
138
|
+
#define FAISS_MAYBE_UNUSED [[maybe_unused]]
|
|
132
139
|
#endif
|
|
133
140
|
|
|
134
141
|
// On non-Windows, FAISS_PACKED handles packing, so these are no-ops
|
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#ifndef THE_SIMD_LEVEL
|
|
11
|
+
#error "THE_SIMD_LEVEL must be defined before including IVFPQScanner_impl.h"
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
#include <faiss/IndexIVFPQ.h>
|
|
15
|
+
#include <faiss/impl/IDSelector.h>
|
|
16
|
+
#include <faiss/impl/ResultHandler.h>
|
|
17
|
+
#include <faiss/impl/pq_code_distance/IVFPQ_QueryTables.h>
|
|
18
|
+
#include <faiss/impl/pq_code_distance/pq_code_distance-inl.h>
|
|
19
|
+
#include <faiss/impl/simd_dispatch.h>
|
|
20
|
+
#include <faiss/invlists/DirectMap.h>
|
|
21
|
+
#include <faiss/utils/distances_dispatch.h>
|
|
22
|
+
#include <faiss/utils/hamming.h>
|
|
23
|
+
|
|
24
|
+
namespace faiss {
|
|
25
|
+
namespace pq_code_distance {
|
|
26
|
+
|
|
27
|
+
template <class C, bool use_sel>
|
|
28
|
+
struct WrappedSearchResult {
|
|
29
|
+
ResultHandler& res;
|
|
30
|
+
size_t nup = 0;
|
|
31
|
+
idx_t list_no;
|
|
32
|
+
|
|
33
|
+
const idx_t* ids;
|
|
34
|
+
const IDSelector* sel;
|
|
35
|
+
|
|
36
|
+
WrappedSearchResult(
|
|
37
|
+
idx_t list_no_in,
|
|
38
|
+
const idx_t* ids_in,
|
|
39
|
+
const IDSelector* sel_in,
|
|
40
|
+
ResultHandler& res_in)
|
|
41
|
+
: res(res_in), list_no(list_no_in), ids(ids_in), sel(sel_in) {}
|
|
42
|
+
|
|
43
|
+
inline bool skip_entry(idx_t j) {
|
|
44
|
+
return use_sel && !sel->is_member(ids[j]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
inline void add(idx_t j, float dis) {
|
|
48
|
+
// Reached only for codes that passed skip_entry — i.e. distance
|
|
49
|
+
// was actually computed for this code (post-filter).
|
|
50
|
+
res.stats.scan_cnt++;
|
|
51
|
+
if (C::cmp(res.threshold, dis)) {
|
|
52
|
+
idx_t id = ids ? ids[j] : lo_build(this->list_no, j);
|
|
53
|
+
if (res.add_result(dis, id)) {
|
|
54
|
+
res.stats.nheap_updates++;
|
|
55
|
+
nup++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/*****************************************************
|
|
62
|
+
* Scaning the codes.
|
|
63
|
+
* The scanning functions call their favorite precompute_*
|
|
64
|
+
* function to precompute the tables they need.
|
|
65
|
+
*****************************************************/
|
|
66
|
+
template <typename IDType, MetricType METRIC_TYPE, class PQCodeDist>
|
|
67
|
+
struct IVFPQScannerT : QueryTables {
|
|
68
|
+
using PQDecoder = typename PQCodeDist::PQDecoder;
|
|
69
|
+
const uint8_t* list_codes = nullptr;
|
|
70
|
+
const IDType* list_ids;
|
|
71
|
+
size_t list_size = 0;
|
|
72
|
+
|
|
73
|
+
IVFPQScannerT(
|
|
74
|
+
const IndexIVFPQ& ivfpq_in,
|
|
75
|
+
const IVFSearchParameters* params_in)
|
|
76
|
+
: QueryTables(ivfpq_in, params_in) {
|
|
77
|
+
FAISS_THROW_IF_NOT(METRIC_TYPE == metric_type);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/*****************************************************
|
|
81
|
+
* Scaning the codes: simple PQ scan.
|
|
82
|
+
*****************************************************/
|
|
83
|
+
|
|
84
|
+
// This is the baseline version of scan_list_with_tables().
|
|
85
|
+
// It demonstrates what this function actually does.
|
|
86
|
+
//
|
|
87
|
+
// /// version of the scan where we use precomputed tables.
|
|
88
|
+
// template <class SearchResultType>
|
|
89
|
+
// void scan_list_with_table(
|
|
90
|
+
// size_t ncode,
|
|
91
|
+
// const uint8_t* codes,
|
|
92
|
+
// SearchResultType& res) const {
|
|
93
|
+
//
|
|
94
|
+
// for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
|
|
95
|
+
// if (res.skip_entry(j)) {
|
|
96
|
+
// continue;
|
|
97
|
+
// }
|
|
98
|
+
// float dis = dis0 + PQCodeDist::distance_single_code(
|
|
99
|
+
// pq, sim_table, codes);
|
|
100
|
+
// res.add(j, dis);
|
|
101
|
+
// }
|
|
102
|
+
// }
|
|
103
|
+
|
|
104
|
+
// This is the modified version of scan_list_with_tables().
|
|
105
|
+
// It was observed that doing manual unrolling of the loop that
|
|
106
|
+
// utilizes distance_single_code() speeds up the computations.
|
|
107
|
+
|
|
108
|
+
/// version of the scan where we use precomputed tables.
|
|
109
|
+
template <class SearchResultType>
|
|
110
|
+
void scan_list_with_table(
|
|
111
|
+
size_t ncode,
|
|
112
|
+
const uint8_t* codes,
|
|
113
|
+
SearchResultType& res) const {
|
|
114
|
+
int counter = 0;
|
|
115
|
+
|
|
116
|
+
size_t saved_j[4] = {0, 0, 0, 0};
|
|
117
|
+
for (size_t j = 0; j < ncode; j++) {
|
|
118
|
+
if (res.skip_entry(j)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
saved_j[0] = (counter == 0) ? j : saved_j[0];
|
|
123
|
+
saved_j[1] = (counter == 1) ? j : saved_j[1];
|
|
124
|
+
saved_j[2] = (counter == 2) ? j : saved_j[2];
|
|
125
|
+
saved_j[3] = (counter == 3) ? j : saved_j[3];
|
|
126
|
+
|
|
127
|
+
counter += 1;
|
|
128
|
+
if (counter == 4) {
|
|
129
|
+
float distance_0 = 0;
|
|
130
|
+
float distance_1 = 0;
|
|
131
|
+
float distance_2 = 0;
|
|
132
|
+
float distance_3 = 0;
|
|
133
|
+
PQCodeDist::distance_four_codes(
|
|
134
|
+
pq.M,
|
|
135
|
+
pq.nbits,
|
|
136
|
+
sim_table,
|
|
137
|
+
codes + saved_j[0] * pq.code_size,
|
|
138
|
+
codes + saved_j[1] * pq.code_size,
|
|
139
|
+
codes + saved_j[2] * pq.code_size,
|
|
140
|
+
codes + saved_j[3] * pq.code_size,
|
|
141
|
+
distance_0,
|
|
142
|
+
distance_1,
|
|
143
|
+
distance_2,
|
|
144
|
+
distance_3);
|
|
145
|
+
|
|
146
|
+
res.add(saved_j[0], dis0 + distance_0);
|
|
147
|
+
res.add(saved_j[1], dis0 + distance_1);
|
|
148
|
+
res.add(saved_j[2], dis0 + distance_2);
|
|
149
|
+
res.add(saved_j[3], dis0 + distance_3);
|
|
150
|
+
counter = 0;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (counter >= 1) {
|
|
155
|
+
float dis = dis0 +
|
|
156
|
+
PQCodeDist::distance_single_code(
|
|
157
|
+
pq.M,
|
|
158
|
+
pq.nbits,
|
|
159
|
+
sim_table,
|
|
160
|
+
codes + saved_j[0] * pq.code_size);
|
|
161
|
+
res.add(saved_j[0], dis);
|
|
162
|
+
}
|
|
163
|
+
if (counter >= 2) {
|
|
164
|
+
float dis = dis0 +
|
|
165
|
+
PQCodeDist::distance_single_code(
|
|
166
|
+
pq.M,
|
|
167
|
+
pq.nbits,
|
|
168
|
+
sim_table,
|
|
169
|
+
codes + saved_j[1] * pq.code_size);
|
|
170
|
+
res.add(saved_j[1], dis);
|
|
171
|
+
}
|
|
172
|
+
if (counter >= 3) {
|
|
173
|
+
float dis = dis0 +
|
|
174
|
+
PQCodeDist::distance_single_code(
|
|
175
|
+
pq.M,
|
|
176
|
+
pq.nbits,
|
|
177
|
+
sim_table,
|
|
178
|
+
codes + saved_j[2] * pq.code_size);
|
|
179
|
+
res.add(saved_j[2], dis);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// tables are not precomputed, but pointers are provided to the
|
|
184
|
+
/// relevant X_c|x_r tables
|
|
185
|
+
template <class SearchResultType>
|
|
186
|
+
void scan_list_with_pointer(
|
|
187
|
+
size_t ncode,
|
|
188
|
+
const uint8_t* codes,
|
|
189
|
+
SearchResultType& res) const {
|
|
190
|
+
for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
|
|
191
|
+
if (res.skip_entry(j)) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
PQDecoder decoder(codes, pq.nbits);
|
|
195
|
+
float dis = dis0;
|
|
196
|
+
const float* tab = sim_table_2;
|
|
197
|
+
|
|
198
|
+
for (size_t m = 0; m < pq.M; m++) {
|
|
199
|
+
int ci = decoder.decode();
|
|
200
|
+
dis += sim_table_ptrs[m][ci] - 2 * tab[ci];
|
|
201
|
+
tab += pq.ksub;
|
|
202
|
+
}
|
|
203
|
+
res.add(j, dis);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/// nothing is precomputed: access residuals on-the-fly
|
|
208
|
+
template <class SearchResultType>
|
|
209
|
+
void scan_on_the_fly_dist(
|
|
210
|
+
size_t ncode,
|
|
211
|
+
const uint8_t* codes,
|
|
212
|
+
SearchResultType& res) const {
|
|
213
|
+
const float* dvec;
|
|
214
|
+
float local_dis0 = 0;
|
|
215
|
+
if (by_residual) {
|
|
216
|
+
if (METRIC_TYPE == METRIC_INNER_PRODUCT) {
|
|
217
|
+
ivfpq.quantizer->reconstruct(key, residual_vec);
|
|
218
|
+
local_dis0 = fvec_inner_product_dispatch(residual_vec, qi, d);
|
|
219
|
+
} else {
|
|
220
|
+
ivfpq.quantizer->compute_residual(qi, residual_vec, key);
|
|
221
|
+
}
|
|
222
|
+
dvec = residual_vec;
|
|
223
|
+
} else {
|
|
224
|
+
dvec = qi;
|
|
225
|
+
local_dis0 = 0;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
|
|
229
|
+
if (res.skip_entry(j)) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
pq.decode(codes, decoded_vec);
|
|
233
|
+
|
|
234
|
+
float dis;
|
|
235
|
+
if (METRIC_TYPE == METRIC_INNER_PRODUCT) {
|
|
236
|
+
dis = local_dis0 +
|
|
237
|
+
fvec_inner_product_dispatch(decoded_vec, qi, d);
|
|
238
|
+
} else {
|
|
239
|
+
dis = fvec_L2sqr_dispatch(decoded_vec, dvec, d);
|
|
240
|
+
}
|
|
241
|
+
res.add(j, dis);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/*****************************************************
|
|
246
|
+
* Scanning codes with polysemous filtering
|
|
247
|
+
*****************************************************/
|
|
248
|
+
|
|
249
|
+
// This is the baseline version of scan_list_polysemous_hc().
|
|
250
|
+
// It demonstrates what this function actually does.
|
|
251
|
+
|
|
252
|
+
// template <class HammingComputer, class SearchResultType>
|
|
253
|
+
// void scan_list_polysemous_hc(
|
|
254
|
+
// size_t ncode,
|
|
255
|
+
// const uint8_t* codes,
|
|
256
|
+
// SearchResultType& res) const {
|
|
257
|
+
// int ht = ivfpq.polysemous_ht;
|
|
258
|
+
// size_t n_hamming_pass = 0, nup = 0;
|
|
259
|
+
//
|
|
260
|
+
// int code_size = pq.code_size;
|
|
261
|
+
//
|
|
262
|
+
// HammingComputer hc(q_code.data(), code_size);
|
|
263
|
+
//
|
|
264
|
+
// for (size_t j = 0; j < ncode; j++, codes += code_size) {
|
|
265
|
+
// if (res.skip_entry(j)) {
|
|
266
|
+
// continue;
|
|
267
|
+
// }
|
|
268
|
+
// const uint8_t* b_code = codes;
|
|
269
|
+
// int hd = hc.hamming(b_code);
|
|
270
|
+
// if (hd < ht) {
|
|
271
|
+
// n_hamming_pass++;
|
|
272
|
+
//
|
|
273
|
+
// float dis =
|
|
274
|
+
// dis0 +
|
|
275
|
+
// PQCodeDist::distance_single_code(
|
|
276
|
+
// pq, sim_table, codes);
|
|
277
|
+
//
|
|
278
|
+
// res.add(j, dis);
|
|
279
|
+
// }
|
|
280
|
+
// }
|
|
281
|
+
// #pragma omp critical
|
|
282
|
+
// { indexIVFPQ_stats.n_hamming_pass += n_hamming_pass; }
|
|
283
|
+
// }
|
|
284
|
+
|
|
285
|
+
// This is the modified version of scan_list_with_tables().
|
|
286
|
+
// It was observed that doing manual unrolling of the loop that
|
|
287
|
+
// utilizes distance_single_code() speeds up the computations.
|
|
288
|
+
|
|
289
|
+
template <class HammingComputer, class SearchResultType>
|
|
290
|
+
void scan_list_polysemous_hc(
|
|
291
|
+
size_t ncode,
|
|
292
|
+
const uint8_t* codes,
|
|
293
|
+
SearchResultType& res) const {
|
|
294
|
+
int ht = ivfpq.polysemous_ht;
|
|
295
|
+
size_t n_hamming_pass = 0;
|
|
296
|
+
|
|
297
|
+
int code_size = static_cast<int>(pq.code_size);
|
|
298
|
+
|
|
299
|
+
size_t saved_j[8];
|
|
300
|
+
int counter = 0;
|
|
301
|
+
|
|
302
|
+
HammingComputer hc(q_code.data(), code_size);
|
|
303
|
+
|
|
304
|
+
for (size_t j = 0; j < (ncode / 4) * 4; j += 4) {
|
|
305
|
+
const uint8_t* b_code = codes + j * code_size;
|
|
306
|
+
|
|
307
|
+
// Unrolling is a key. Basically, doing multiple popcount
|
|
308
|
+
// operations one after another speeds things up.
|
|
309
|
+
|
|
310
|
+
// 9999999 is just an arbitrary large number
|
|
311
|
+
int hd0 = (res.skip_entry(j + 0))
|
|
312
|
+
? 99999999
|
|
313
|
+
: hc.hamming(b_code + 0 * code_size);
|
|
314
|
+
int hd1 = (res.skip_entry(j + 1))
|
|
315
|
+
? 99999999
|
|
316
|
+
: hc.hamming(b_code + 1 * code_size);
|
|
317
|
+
int hd2 = (res.skip_entry(j + 2))
|
|
318
|
+
? 99999999
|
|
319
|
+
: hc.hamming(b_code + 2 * code_size);
|
|
320
|
+
int hd3 = (res.skip_entry(j + 3))
|
|
321
|
+
? 99999999
|
|
322
|
+
: hc.hamming(b_code + 3 * code_size);
|
|
323
|
+
|
|
324
|
+
saved_j[counter] = j + 0;
|
|
325
|
+
counter = (hd0 < ht) ? (counter + 1) : counter;
|
|
326
|
+
saved_j[counter] = j + 1;
|
|
327
|
+
counter = (hd1 < ht) ? (counter + 1) : counter;
|
|
328
|
+
saved_j[counter] = j + 2;
|
|
329
|
+
counter = (hd2 < ht) ? (counter + 1) : counter;
|
|
330
|
+
saved_j[counter] = j + 3;
|
|
331
|
+
counter = (hd3 < ht) ? (counter + 1) : counter;
|
|
332
|
+
|
|
333
|
+
if (counter >= 4) {
|
|
334
|
+
// process four codes at the same time
|
|
335
|
+
n_hamming_pass += 4;
|
|
336
|
+
|
|
337
|
+
float distance_0 = dis0;
|
|
338
|
+
float distance_1 = dis0;
|
|
339
|
+
float distance_2 = dis0;
|
|
340
|
+
float distance_3 = dis0;
|
|
341
|
+
PQCodeDist::distance_four_codes(
|
|
342
|
+
pq.M,
|
|
343
|
+
pq.nbits,
|
|
344
|
+
sim_table,
|
|
345
|
+
codes + saved_j[0] * pq.code_size,
|
|
346
|
+
codes + saved_j[1] * pq.code_size,
|
|
347
|
+
codes + saved_j[2] * pq.code_size,
|
|
348
|
+
codes + saved_j[3] * pq.code_size,
|
|
349
|
+
distance_0,
|
|
350
|
+
distance_1,
|
|
351
|
+
distance_2,
|
|
352
|
+
distance_3);
|
|
353
|
+
|
|
354
|
+
res.add(saved_j[0], dis0 + distance_0);
|
|
355
|
+
res.add(saved_j[1], dis0 + distance_1);
|
|
356
|
+
res.add(saved_j[2], dis0 + distance_2);
|
|
357
|
+
res.add(saved_j[3], dis0 + distance_3);
|
|
358
|
+
|
|
359
|
+
//
|
|
360
|
+
counter -= 4;
|
|
361
|
+
saved_j[0] = saved_j[4];
|
|
362
|
+
saved_j[1] = saved_j[5];
|
|
363
|
+
saved_j[2] = saved_j[6];
|
|
364
|
+
saved_j[3] = saved_j[7];
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
for (int kk = 0; kk < counter; kk++) {
|
|
369
|
+
n_hamming_pass++;
|
|
370
|
+
|
|
371
|
+
float dis = dis0 +
|
|
372
|
+
PQCodeDist::distance_single_code(
|
|
373
|
+
pq.M,
|
|
374
|
+
pq.nbits,
|
|
375
|
+
sim_table,
|
|
376
|
+
codes + saved_j[kk] * pq.code_size);
|
|
377
|
+
|
|
378
|
+
res.add(saved_j[kk], dis);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// process leftovers
|
|
382
|
+
for (size_t j = (ncode / 4) * 4; j < ncode; j++) {
|
|
383
|
+
if (res.skip_entry(j)) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
const uint8_t* b_code = codes + j * code_size;
|
|
387
|
+
int hd = hc.hamming(b_code);
|
|
388
|
+
if (hd < ht) {
|
|
389
|
+
n_hamming_pass++;
|
|
390
|
+
|
|
391
|
+
float dis = dis0 +
|
|
392
|
+
PQCodeDist::distance_single_code(
|
|
393
|
+
pq.M,
|
|
394
|
+
pq.nbits,
|
|
395
|
+
sim_table,
|
|
396
|
+
codes + j * code_size);
|
|
397
|
+
|
|
398
|
+
res.add(j, dis);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
#pragma omp critical
|
|
403
|
+
{
|
|
404
|
+
indexIVFPQ_stats.n_hamming_pass += n_hamming_pass;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
template <class SearchResultType>
|
|
409
|
+
void scan_list_polysemous(
|
|
410
|
+
size_t ncode,
|
|
411
|
+
const uint8_t* codes,
|
|
412
|
+
SearchResultType& res) const {
|
|
413
|
+
with_HammingComputer<PQCodeDist::simd_level>(
|
|
414
|
+
pq.code_size, [&]<class HammingComputer>() {
|
|
415
|
+
this->scan_list_polysemous_hc<
|
|
416
|
+
HammingComputer,
|
|
417
|
+
SearchResultType>(ncode, codes, res);
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
/* We put as many parameters as possible in template. Hopefully the
|
|
423
|
+
* gain in runtime is worth the code bloat.
|
|
424
|
+
*
|
|
425
|
+
* C is the comparator < or >, it is directly related to METRIC_TYPE.
|
|
426
|
+
*
|
|
427
|
+
* precompute_mode is how much we precompute (2 = precompute distance tables,
|
|
428
|
+
* 1 = precompute pointers to distances, 0 = compute distances one by one).
|
|
429
|
+
* Currently only 2 is supported
|
|
430
|
+
*
|
|
431
|
+
* use_sel: store or ignore the IDSelector
|
|
432
|
+
*/
|
|
433
|
+
template <MetricType METRIC_TYPE, class C, class PQCodeDist, bool use_sel>
|
|
434
|
+
struct IVFPQScanner : IVFPQScannerT<idx_t, METRIC_TYPE, PQCodeDist>,
|
|
435
|
+
InvertedListScanner {
|
|
436
|
+
using InvertedListScanner::scan_codes;
|
|
437
|
+
int precompute_mode;
|
|
438
|
+
const IDSelector* sel;
|
|
439
|
+
|
|
440
|
+
IVFPQScanner(
|
|
441
|
+
const IndexIVFPQ& ivfpq_in,
|
|
442
|
+
bool store_pairs_in,
|
|
443
|
+
int precompute_mode_in,
|
|
444
|
+
const IDSelector* sel_in)
|
|
445
|
+
: IVFPQScannerT<idx_t, METRIC_TYPE, PQCodeDist>(ivfpq_in, nullptr),
|
|
446
|
+
precompute_mode(precompute_mode_in),
|
|
447
|
+
sel(sel_in) {
|
|
448
|
+
this->store_pairs = store_pairs_in;
|
|
449
|
+
this->keep_max = is_similarity_metric(METRIC_TYPE);
|
|
450
|
+
this->code_size = this->pq.code_size;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
void set_query(const float* query) override {
|
|
454
|
+
this->init_query(query);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
void set_list(idx_t list_no_in, float coarse_dis_in) override {
|
|
458
|
+
this->list_no = list_no_in;
|
|
459
|
+
this->init_list(list_no_in, coarse_dis_in, precompute_mode);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
float distance_to_code(const uint8_t* code) const override {
|
|
463
|
+
FAISS_THROW_IF_NOT(precompute_mode == 2);
|
|
464
|
+
float dis = this->dis0 +
|
|
465
|
+
PQCodeDist::distance_single_code(
|
|
466
|
+
this->pq.M, this->pq.nbits, this->sim_table, code);
|
|
467
|
+
return dis;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
size_t scan_codes(
|
|
471
|
+
size_t ncode,
|
|
472
|
+
const uint8_t* codes,
|
|
473
|
+
const idx_t* ids,
|
|
474
|
+
ResultHandler& handler) const override {
|
|
475
|
+
WrappedSearchResult<C, use_sel> res(
|
|
476
|
+
this->key,
|
|
477
|
+
this->store_pairs ? nullptr : ids,
|
|
478
|
+
this->sel,
|
|
479
|
+
handler);
|
|
480
|
+
|
|
481
|
+
if (this->polysemous_ht > 0) {
|
|
482
|
+
FAISS_THROW_IF_NOT(precompute_mode == 2);
|
|
483
|
+
this->scan_list_polysemous(ncode, codes, res);
|
|
484
|
+
} else if (precompute_mode == 2) {
|
|
485
|
+
this->scan_list_with_table(ncode, codes, res);
|
|
486
|
+
} else if (precompute_mode == 1) {
|
|
487
|
+
this->scan_list_with_pointer(ncode, codes, res);
|
|
488
|
+
} else if (precompute_mode == 0) {
|
|
489
|
+
this->scan_on_the_fly_dist(ncode, codes, res);
|
|
490
|
+
} else {
|
|
491
|
+
FAISS_THROW_MSG("bad precomp mode");
|
|
492
|
+
}
|
|
493
|
+
return res.nup;
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
template <SIMDLevel SL>
|
|
498
|
+
InvertedListScanner* make_IVFPQInvertedListScanner(
|
|
499
|
+
const IndexIVFPQ& ivfpq,
|
|
500
|
+
bool store_pairs,
|
|
501
|
+
const IDSelector* sel);
|
|
502
|
+
|
|
503
|
+
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
|
|
504
|
+
template <>
|
|
505
|
+
InvertedListScanner* make_IVFPQInvertedListScanner<THE_SIMD_LEVEL>(
|
|
506
|
+
const IndexIVFPQ& ivfpq,
|
|
507
|
+
bool store_pairs,
|
|
508
|
+
const IDSelector* sel) {
|
|
509
|
+
auto make = [&]<class PQCodeDist, bool use_sel>() -> InvertedListScanner* {
|
|
510
|
+
if (ivfpq.metric_type == METRIC_INNER_PRODUCT) {
|
|
511
|
+
return new IVFPQScanner<
|
|
512
|
+
METRIC_INNER_PRODUCT,
|
|
513
|
+
CMin<float, idx_t>,
|
|
514
|
+
PQCodeDist,
|
|
515
|
+
use_sel>(ivfpq, store_pairs, 2, sel);
|
|
516
|
+
} else if (ivfpq.metric_type == METRIC_L2) {
|
|
517
|
+
return new IVFPQScanner<
|
|
518
|
+
METRIC_L2,
|
|
519
|
+
CMax<float, idx_t>,
|
|
520
|
+
PQCodeDist,
|
|
521
|
+
use_sel>(ivfpq, store_pairs, 2, sel);
|
|
522
|
+
} else {
|
|
523
|
+
FAISS_THROW_MSG("unsupported metric type");
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
auto with_decoder = [&]<bool use_sel>() -> InvertedListScanner* {
|
|
528
|
+
if (ivfpq.pq.nbits == 8) {
|
|
529
|
+
return make.template
|
|
530
|
+
operator()<PQCodeDistance<PQDecoder8, THE_SIMD_LEVEL>, use_sel>();
|
|
531
|
+
} else if (ivfpq.pq.nbits == 16) {
|
|
532
|
+
return make.template
|
|
533
|
+
operator()<PQCodeDistance<PQDecoder16, THE_SIMD_LEVEL>, use_sel>();
|
|
534
|
+
} else {
|
|
535
|
+
return make.template operator()<
|
|
536
|
+
PQCodeDistance<PQDecoderGeneric, THE_SIMD_LEVEL>,
|
|
537
|
+
use_sel>();
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
if (sel) {
|
|
542
|
+
return with_decoder.template operator()<true>();
|
|
543
|
+
} else {
|
|
544
|
+
return with_decoder.template operator()<false>();
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
} // namespace pq_code_distance
|
|
549
|
+
} // namespace faiss
|