faiss 0.6.0 → 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 +4 -0
- data/ext/faiss/extconf.rb +2 -1
- data/ext/faiss/{index_rb.cpp → index.cpp} +1 -1
- data/ext/faiss/index_binary.cpp +1 -1
- data/ext/faiss/kmeans.cpp +1 -1
- data/ext/faiss/pca_matrix.cpp +1 -1
- data/ext/faiss/product_quantizer.cpp +1 -1
- data/ext/faiss/{utils_rb.cpp → utils.cpp} +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +93 -80
- data/vendor/faiss/faiss/Clustering.cpp +39 -240
- data/vendor/faiss/faiss/Clustering.h +6 -0
- data/vendor/faiss/faiss/IVFlib.cpp +41 -21
- data/vendor/faiss/faiss/Index.cpp +6 -5
- data/vendor/faiss/faiss/Index.h +5 -5
- data/vendor/faiss/faiss/Index2Layer.cpp +37 -53
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +49 -37
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +36 -34
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +4 -1
- data/vendor/faiss/faiss/IndexBinary.cpp +5 -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 +84 -92
- 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 +87 -415
- data/vendor/faiss/faiss/IndexFastScan.cpp +72 -109
- data/vendor/faiss/faiss/IndexFastScan.h +25 -23
- data/vendor/faiss/faiss/IndexFlat.cpp +27 -20
- data/vendor/faiss/faiss/IndexFlat.h +21 -18
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +42 -19
- data/vendor/faiss/faiss/IndexHNSW.cpp +283 -145
- data/vendor/faiss/faiss/IndexHNSW.h +16 -2
- data/vendor/faiss/faiss/IndexIDMap.cpp +25 -21
- data/vendor/faiss/faiss/IndexIDMap.h +9 -7
- data/vendor/faiss/faiss/IndexIVF.cpp +465 -362
- data/vendor/faiss/faiss/IndexIVF.h +33 -12
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +77 -74
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +96 -93
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -1
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +357 -238
- data/vendor/faiss/faiss/IndexIVFFastScan.h +42 -41
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +36 -68
- data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +53 -30
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +3 -1
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +18 -15
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +71 -843
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +151 -121
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +3 -0
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +21 -17
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +26 -39
- data/vendor/faiss/faiss/IndexIVFRaBitQ.h +2 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +475 -476
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +248 -93
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +41 -127
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
- data/vendor/faiss/faiss/IndexLSH.cpp +36 -19
- data/vendor/faiss/faiss/IndexLattice.cpp +13 -13
- data/vendor/faiss/faiss/IndexNNDescent.cpp +36 -21
- data/vendor/faiss/faiss/IndexNNDescent.h +2 -2
- data/vendor/faiss/faiss/IndexNSG.cpp +39 -23
- data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +31 -11
- data/vendor/faiss/faiss/IndexPQ.cpp +128 -221
- 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 +11 -36
- data/vendor/faiss/faiss/IndexRaBitQ.h +2 -1
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +41 -277
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +183 -27
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -25
- 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 +10 -9
- 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 +14 -7
- data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
- data/vendor/faiss/faiss/SuperKMeans.h +97 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +237 -149
- data/vendor/faiss/faiss/VectorTransform.h +16 -16
- data/vendor/faiss/faiss/build.cpp +23 -0
- data/vendor/faiss/faiss/build.h +15 -0
- data/vendor/faiss/faiss/clone_index.cpp +48 -47
- 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/factory_tools.cpp +5 -0
- 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 +29 -25
- 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 -0
- 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 +16 -16
- data/vendor/faiss/faiss/impl/CodePacker.cpp +3 -3
- data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +1 -1
- data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
- data/vendor/faiss/faiss/impl/FaissAssert.h +6 -3
- data/vendor/faiss/faiss/impl/FaissException.h +50 -3
- data/vendor/faiss/faiss/impl/HNSW.cpp +92 -317
- data/vendor/faiss/faiss/impl/HNSW.h +13 -34
- 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 +82 -77
- data/vendor/faiss/faiss/impl/NNDescent.cpp +62 -25
- data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +38 -21
- data/vendor/faiss/faiss/impl/NSG.h +4 -4
- data/vendor/faiss/faiss/impl/Panorama.cpp +23 -6
- data/vendor/faiss/faiss/impl/Panorama.h +258 -87
- 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 +46 -32
- 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 +30 -23
- data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +55 -49
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +65 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +296 -283
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +26 -23
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
- data/vendor/faiss/faiss/impl/ResultHandler.h +99 -75
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +52 -4
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +27 -1
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
- data/vendor/faiss/faiss/impl/VisitedTable.h +7 -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 +8 -3
- 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} +169 -2
- 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 -356
- 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} +282 -134
- 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 +1132 -45
- data/vendor/faiss/faiss/impl/index_read_utils.h +1 -1
- data/vendor/faiss/faiss/impl/index_write.cpp +95 -13
- 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 +37 -23
- data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
- data/vendor/faiss/faiss/impl/mapped_io.cpp +6 -6
- 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/pq_code_distance/{pq_code_distance-avx2.cpp → pq_code_distance-avx2.h} +9 -13
- data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx512.cpp → pq_code_distance-avx512.h} +9 -57
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +29 -111
- 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 +238 -5
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -7
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +68 -0
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +311 -477
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
- data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +1 -1
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +3 -2
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +102 -11
- data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +27 -1
- data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +3 -3
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +148 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +167 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +59 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +163 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +311 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +192 -8
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +12 -0
- data/vendor/faiss/faiss/impl/simd_dispatch.h +100 -66
- data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
- data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +264 -172
- 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 +270 -218
- 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 +86 -18
- data/vendor/faiss/faiss/index_io.h +24 -0
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +66 -16
- 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 +13 -13
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
- 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 +18 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +12 -3
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +7 -2
- data/vendor/faiss/faiss/utils/Heap.cpp +10 -10
- data/vendor/faiss/faiss/utils/NeuralNet.cpp +47 -36
- 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 +390 -560
- data/vendor/faiss/faiss/utils/distances.h +20 -1
- data/vendor/faiss/faiss/utils/distances_dispatch.h +117 -37
- 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 +5 -177
- data/vendor/faiss/faiss/utils/extra_distances.cpp +9 -8
- data/vendor/faiss/faiss/utils/extra_distances.h +32 -6
- 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 +2 -2
- 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 +57 -536
- 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 +5 -1
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +213 -4
- data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +163 -10
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +250 -4
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +7 -4
- 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 +2 -1
- 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 +17 -5
- data/vendor/faiss/faiss/utils/simd_levels.h +93 -1
- data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
- data/vendor/faiss/faiss/utils/utils.cpp +5 -5
- data/vendor/faiss/faiss/utils/utils.h +3 -3
- metadata +119 -34
- data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
- data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -224
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -230
- 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 -235
- 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 -449
- 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 -365
- /data/ext/faiss/{utils_rb.h → utils.h} +0 -0
|
@@ -0,0 +1,460 @@
|
|
|
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
|
+
/*
|
|
9
|
+
* Per-ISA implementation of Hamming distance computation for
|
|
10
|
+
* IndexBinaryIVF. Included once per SIMD TU with THE_SIMD_LEVEL
|
|
11
|
+
* set to the desired SIMDLevel.
|
|
12
|
+
*
|
|
13
|
+
* Contains: IVFBinaryScannerL2, search_knn_hamming_count,
|
|
14
|
+
* BlockSearch, BlockSearchVariableK, search_knn_hamming_per_invlist.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#pragma once
|
|
18
|
+
|
|
19
|
+
#ifndef THE_SIMD_LEVEL
|
|
20
|
+
#error "THE_SIMD_LEVEL must be defined before including this file"
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
#include <faiss/utils/hamming_distance/hamming_computer.h>
|
|
24
|
+
|
|
25
|
+
#include <algorithm>
|
|
26
|
+
#include <cinttypes>
|
|
27
|
+
#include <limits>
|
|
28
|
+
#include <memory>
|
|
29
|
+
|
|
30
|
+
#include <faiss/IndexBinaryIVF.h>
|
|
31
|
+
#include <faiss/impl/AuxIndexStructures.h>
|
|
32
|
+
#include <faiss/impl/FaissAssert.h>
|
|
33
|
+
#include <faiss/impl/binary_hamming/dispatch.h>
|
|
34
|
+
#include <faiss/utils/Heap.h>
|
|
35
|
+
#include <faiss/utils/hamming.h>
|
|
36
|
+
#include <faiss/utils/sorting.h>
|
|
37
|
+
|
|
38
|
+
namespace faiss {
|
|
39
|
+
|
|
40
|
+
namespace {
|
|
41
|
+
|
|
42
|
+
template <class HammingComputer>
|
|
43
|
+
struct IVFBinaryScannerL2 : BinaryInvertedListScanner {
|
|
44
|
+
HammingComputer hc;
|
|
45
|
+
size_t code_size;
|
|
46
|
+
bool store_pairs;
|
|
47
|
+
|
|
48
|
+
IVFBinaryScannerL2(size_t code_size_, bool store_pairs_)
|
|
49
|
+
: code_size(code_size_), store_pairs(store_pairs_) {}
|
|
50
|
+
|
|
51
|
+
void set_query(const uint8_t* query_vector) override {
|
|
52
|
+
hc.set(query_vector, code_size);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
idx_t list_no = 0;
|
|
56
|
+
void set_list(idx_t list_no_2, uint8_t /* coarse_dis */) override {
|
|
57
|
+
this->list_no = list_no_2;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
uint32_t distance_to_code(const uint8_t* code) const override {
|
|
61
|
+
return hc.hamming(code);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
size_t scan_codes(
|
|
65
|
+
size_t n,
|
|
66
|
+
const uint8_t* __restrict codes,
|
|
67
|
+
const idx_t* __restrict ids,
|
|
68
|
+
int32_t* __restrict simi,
|
|
69
|
+
idx_t* __restrict idxi,
|
|
70
|
+
size_t k) const override {
|
|
71
|
+
using C = CMax<int32_t, idx_t>;
|
|
72
|
+
|
|
73
|
+
size_t nup = 0;
|
|
74
|
+
for (size_t j = 0; j < n; j++) {
|
|
75
|
+
uint32_t dis = hc.hamming(codes);
|
|
76
|
+
if (dis < static_cast<uint32_t>(simi[0])) {
|
|
77
|
+
idx_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
78
|
+
heap_replace_top<C>(k, simi, idxi, dis, id);
|
|
79
|
+
nup++;
|
|
80
|
+
}
|
|
81
|
+
codes += code_size;
|
|
82
|
+
}
|
|
83
|
+
return nup;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void scan_codes_range(
|
|
87
|
+
size_t n,
|
|
88
|
+
const uint8_t* __restrict codes,
|
|
89
|
+
const idx_t* __restrict ids,
|
|
90
|
+
int radius,
|
|
91
|
+
RangeQueryResult& result) const override {
|
|
92
|
+
for (size_t j = 0; j < n; j++) {
|
|
93
|
+
uint32_t dis = hc.hamming(codes);
|
|
94
|
+
if (dis < static_cast<uint32_t>(radius)) {
|
|
95
|
+
int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
96
|
+
result.add(dis, id);
|
|
97
|
+
}
|
|
98
|
+
codes += code_size;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
template <class HammingComputer, bool store_pairs>
|
|
104
|
+
void search_knn_hamming_count(
|
|
105
|
+
const IndexBinaryIVF* ivf,
|
|
106
|
+
size_t nx,
|
|
107
|
+
const uint8_t* __restrict x,
|
|
108
|
+
const idx_t* __restrict keys,
|
|
109
|
+
int k,
|
|
110
|
+
int32_t* __restrict distances,
|
|
111
|
+
idx_t* __restrict labels,
|
|
112
|
+
const IVFSearchParameters* params) {
|
|
113
|
+
const int nBuckets = ivf->d + 1;
|
|
114
|
+
std::vector<int> all_counters(nx * nBuckets, 0);
|
|
115
|
+
std::unique_ptr<idx_t[]> all_ids_per_dis(new idx_t[nx * nBuckets * k]);
|
|
116
|
+
|
|
117
|
+
idx_t nprobe = params ? params->nprobe : ivf->nprobe;
|
|
118
|
+
nprobe = std::min((idx_t)ivf->nlist, nprobe);
|
|
119
|
+
idx_t max_codes = params ? params->max_codes : ivf->max_codes;
|
|
120
|
+
|
|
121
|
+
std::vector<HCounterState<HammingComputer>> cs;
|
|
122
|
+
cs.reserve(nx);
|
|
123
|
+
for (size_t i = 0; i < nx; ++i) {
|
|
124
|
+
cs.push_back(
|
|
125
|
+
HCounterState<HammingComputer>(
|
|
126
|
+
all_counters.data() + i * nBuckets,
|
|
127
|
+
all_ids_per_dis.get() + i * nBuckets * k,
|
|
128
|
+
x + i * ivf->code_size,
|
|
129
|
+
ivf->d,
|
|
130
|
+
k));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
size_t nlistv = 0, ndis = 0;
|
|
134
|
+
|
|
135
|
+
#pragma omp parallel for reduction(+ : nlistv, ndis)
|
|
136
|
+
for (int64_t i = 0; i < static_cast<int64_t>(nx); i++) {
|
|
137
|
+
const idx_t* keysi = keys + i * nprobe;
|
|
138
|
+
HCounterState<HammingComputer>& csi = cs[i];
|
|
139
|
+
|
|
140
|
+
size_t nscan = 0;
|
|
141
|
+
|
|
142
|
+
for (idx_t ik = 0; ik < nprobe; ik++) {
|
|
143
|
+
idx_t key = keysi[ik]; /* select the list */
|
|
144
|
+
if (key < 0) {
|
|
145
|
+
// not enough centroids for multiprobe
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
149
|
+
key < (idx_t)ivf->nlist,
|
|
150
|
+
"Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n",
|
|
151
|
+
key,
|
|
152
|
+
static_cast<size_t>(ik),
|
|
153
|
+
ivf->nlist);
|
|
154
|
+
|
|
155
|
+
nlistv++;
|
|
156
|
+
size_t list_size = ivf->invlists->list_size(key);
|
|
157
|
+
size_t list_size_max = static_cast<size_t>(max_codes) - nscan;
|
|
158
|
+
if (list_size > list_size_max) {
|
|
159
|
+
list_size = list_size_max;
|
|
160
|
+
}
|
|
161
|
+
InvertedLists::ScopedCodes scodes(ivf->invlists, key);
|
|
162
|
+
const uint8_t* list_vecs = scodes.get();
|
|
163
|
+
const idx_t* ids =
|
|
164
|
+
store_pairs ? nullptr : ivf->invlists->get_ids(key);
|
|
165
|
+
|
|
166
|
+
for (size_t j = 0; j < list_size; j++) {
|
|
167
|
+
const uint8_t* yj = list_vecs + ivf->code_size * j;
|
|
168
|
+
|
|
169
|
+
idx_t id = store_pairs ? (key << 32 | j) : ids[j];
|
|
170
|
+
csi.update_counter(yj, id);
|
|
171
|
+
}
|
|
172
|
+
if (ids) {
|
|
173
|
+
ivf->invlists->release_ids(key, ids);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
nscan += list_size;
|
|
177
|
+
if (nscan >= static_cast<size_t>(max_codes)) {
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
ndis += nscan;
|
|
182
|
+
|
|
183
|
+
int nres = 0;
|
|
184
|
+
for (int b = 0; b < nBuckets && nres < k; b++) {
|
|
185
|
+
for (int l = 0; l < csi.counters[b] && nres < k; l++) {
|
|
186
|
+
labels[i * k + nres] = csi.ids_per_dis[b * k + l];
|
|
187
|
+
distances[i * k + nres] = b;
|
|
188
|
+
nres++;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
while (nres < k) {
|
|
192
|
+
labels[i * k + nres] = -1;
|
|
193
|
+
distances[i * k + nres] = std::numeric_limits<int32_t>::max();
|
|
194
|
+
++nres;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
indexIVF_stats.nq += nx;
|
|
199
|
+
indexIVF_stats.nlist += nlistv;
|
|
200
|
+
indexIVF_stats.ndis += ndis;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/* Manages NQ queries at a time, stores results */
|
|
204
|
+
template <class HammingComputer, int NQ, int K>
|
|
205
|
+
struct BlockSearch {
|
|
206
|
+
HammingComputer hcs[NQ];
|
|
207
|
+
// heaps to update for each query
|
|
208
|
+
int32_t* distances[NQ] = {};
|
|
209
|
+
idx_t* labels[NQ] = {};
|
|
210
|
+
// curent top of heap
|
|
211
|
+
int32_t heap_tops[NQ] = {};
|
|
212
|
+
|
|
213
|
+
BlockSearch(
|
|
214
|
+
size_t code_size,
|
|
215
|
+
const uint8_t* __restrict x,
|
|
216
|
+
const int32_t* __restrict keys,
|
|
217
|
+
int32_t* __restrict all_distances,
|
|
218
|
+
idx_t* __restrict all_labels) {
|
|
219
|
+
for (idx_t q = 0; q < NQ; q++) {
|
|
220
|
+
idx_t qno = keys[q];
|
|
221
|
+
hcs[q] = HammingComputer(x + qno * code_size, code_size);
|
|
222
|
+
distances[q] = all_distances + qno * K;
|
|
223
|
+
labels[q] = all_labels + qno * K;
|
|
224
|
+
heap_tops[q] = distances[q][0];
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
void add_bcode(const uint8_t* bcode, idx_t id) {
|
|
229
|
+
using C = CMax<int32_t, idx_t>;
|
|
230
|
+
for (int q = 0; q < NQ; q++) {
|
|
231
|
+
int dis = hcs[q].hamming(bcode);
|
|
232
|
+
if (dis < heap_tops[q]) {
|
|
233
|
+
heap_replace_top<C>(K, distances[q], labels[q], dis, id);
|
|
234
|
+
heap_tops[q] = distances[q][0];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
template <class HammingComputer, int NQ>
|
|
241
|
+
struct BlockSearchVariableK {
|
|
242
|
+
int k;
|
|
243
|
+
HammingComputer hcs[NQ];
|
|
244
|
+
// heaps to update for each query
|
|
245
|
+
int32_t* distances[NQ] = {};
|
|
246
|
+
idx_t* labels[NQ] = {};
|
|
247
|
+
// curent top of heap
|
|
248
|
+
int32_t heap_tops[NQ] = {};
|
|
249
|
+
|
|
250
|
+
BlockSearchVariableK(
|
|
251
|
+
size_t code_size,
|
|
252
|
+
int k_,
|
|
253
|
+
const uint8_t* __restrict x,
|
|
254
|
+
const int32_t* __restrict keys,
|
|
255
|
+
int32_t* __restrict all_distances,
|
|
256
|
+
idx_t* __restrict all_labels)
|
|
257
|
+
: k(k_) {
|
|
258
|
+
for (idx_t q = 0; q < NQ; q++) {
|
|
259
|
+
idx_t qno = keys[q];
|
|
260
|
+
hcs[q] = HammingComputer(x + qno * code_size, code_size);
|
|
261
|
+
distances[q] = all_distances + qno * k;
|
|
262
|
+
labels[q] = all_labels + qno * k;
|
|
263
|
+
heap_tops[q] = distances[q][0];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
void add_bcode(const uint8_t* bcode, idx_t id) {
|
|
268
|
+
using C = CMax<int32_t, idx_t>;
|
|
269
|
+
for (int q = 0; q < NQ; q++) {
|
|
270
|
+
int dis = hcs[q].hamming(bcode);
|
|
271
|
+
if (dis < heap_tops[q]) {
|
|
272
|
+
heap_replace_top<C>(k, distances[q], labels[q], dis, id);
|
|
273
|
+
heap_tops[q] = distances[q][0];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
template <class HammingComputer>
|
|
280
|
+
void search_knn_hamming_per_invlist(
|
|
281
|
+
const IndexBinaryIVF* ivf,
|
|
282
|
+
size_t n,
|
|
283
|
+
const uint8_t* __restrict x,
|
|
284
|
+
idx_t k,
|
|
285
|
+
const idx_t* __restrict keys_in,
|
|
286
|
+
const int32_t* __restrict /* coarse_dis */,
|
|
287
|
+
int32_t* __restrict distances,
|
|
288
|
+
idx_t* __restrict labels,
|
|
289
|
+
bool store_pairs,
|
|
290
|
+
const IVFSearchParameters* params) {
|
|
291
|
+
idx_t nprobe = params ? params->nprobe : ivf->nprobe;
|
|
292
|
+
nprobe = std::min((idx_t)ivf->nlist, nprobe);
|
|
293
|
+
idx_t max_codes = params ? params->max_codes : ivf->max_codes;
|
|
294
|
+
FAISS_THROW_IF_NOT(max_codes == 0);
|
|
295
|
+
FAISS_THROW_IF_NOT(!store_pairs);
|
|
296
|
+
|
|
297
|
+
// reorder buckets
|
|
298
|
+
std::vector<int64_t> lims(n + 1);
|
|
299
|
+
int32_t* keys = new int32_t[n * nprobe];
|
|
300
|
+
std::unique_ptr<int32_t[]> delete_keys(keys);
|
|
301
|
+
for (size_t i = 0; i < n * static_cast<size_t>(nprobe); i++) {
|
|
302
|
+
keys[i] = static_cast<int32_t>(keys_in[i]);
|
|
303
|
+
}
|
|
304
|
+
matrix_bucket_sort_inplace(
|
|
305
|
+
n, nprobe, keys, static_cast<int32_t>(ivf->nlist), lims.data(), 0);
|
|
306
|
+
|
|
307
|
+
using C = CMax<int32_t, idx_t>;
|
|
308
|
+
heap_heapify<C>(n * k, distances, labels);
|
|
309
|
+
const size_t code_size = ivf->code_size;
|
|
310
|
+
|
|
311
|
+
for (size_t l = 0; l < ivf->nlist; l++) {
|
|
312
|
+
idx_t l0 = lims[l], nq = lims[l + 1] - l0;
|
|
313
|
+
|
|
314
|
+
InvertedLists::ScopedCodes scodes(ivf->invlists, l);
|
|
315
|
+
InvertedLists::ScopedIds sidx(ivf->invlists, l);
|
|
316
|
+
idx_t nb = ivf->invlists->list_size(l);
|
|
317
|
+
const uint8_t* bcodes = scodes.get();
|
|
318
|
+
const idx_t* ids = sidx.get();
|
|
319
|
+
|
|
320
|
+
idx_t i = 0;
|
|
321
|
+
|
|
322
|
+
// process as much as possible by blocks
|
|
323
|
+
constexpr int BS = 4;
|
|
324
|
+
|
|
325
|
+
if (k == 1) {
|
|
326
|
+
for (; i + BS <= nq; i += BS) {
|
|
327
|
+
BlockSearch<HammingComputer, BS, 1> bc(
|
|
328
|
+
code_size, x, keys + l0 + i, distances, labels);
|
|
329
|
+
for (idx_t j = 0; j < nb; j++) {
|
|
330
|
+
bc.add_bcode(bcodes + j * code_size, ids[j]);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
} else if (k == 2) {
|
|
334
|
+
for (; i + BS <= nq; i += BS) {
|
|
335
|
+
BlockSearch<HammingComputer, BS, 2> bc(
|
|
336
|
+
code_size, x, keys + l0 + i, distances, labels);
|
|
337
|
+
for (idx_t j = 0; j < nb; j++) {
|
|
338
|
+
bc.add_bcode(bcodes + j * code_size, ids[j]);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
} else if (k == 4) {
|
|
342
|
+
for (; i + BS <= nq; i += BS) {
|
|
343
|
+
BlockSearch<HammingComputer, BS, 4> bc(
|
|
344
|
+
code_size, x, keys + l0 + i, distances, labels);
|
|
345
|
+
for (idx_t j = 0; j < nb; j++) {
|
|
346
|
+
bc.add_bcode(bcodes + j * code_size, ids[j]);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
} else {
|
|
350
|
+
for (; i + BS <= nq; i += BS) {
|
|
351
|
+
BlockSearchVariableK<HammingComputer, BS> bc(
|
|
352
|
+
code_size,
|
|
353
|
+
static_cast<int>(k),
|
|
354
|
+
x,
|
|
355
|
+
keys + l0 + i,
|
|
356
|
+
distances,
|
|
357
|
+
labels);
|
|
358
|
+
for (idx_t j = 0; j < nb; j++) {
|
|
359
|
+
bc.add_bcode(bcodes + j * code_size, ids[j]);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// leftovers
|
|
365
|
+
for (; i < nq; i++) {
|
|
366
|
+
idx_t qno = keys[l0 + i];
|
|
367
|
+
HammingComputer hc(
|
|
368
|
+
x + qno * code_size, static_cast<int>(code_size));
|
|
369
|
+
idx_t* __restrict idxi = labels + qno * k;
|
|
370
|
+
int32_t* __restrict simi = distances + qno * k;
|
|
371
|
+
int32_t simi0 = simi[0];
|
|
372
|
+
for (idx_t j = 0; j < nb; j++) {
|
|
373
|
+
int dis = hc.hamming(bcodes + j * code_size);
|
|
374
|
+
|
|
375
|
+
if (dis < simi0) {
|
|
376
|
+
idx_t id = store_pairs ? lo_build(l, j) : ids[j];
|
|
377
|
+
heap_replace_top<C>(k, simi, idxi, dis, id);
|
|
378
|
+
simi0 = simi[0];
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
for (size_t i = 0; i < n; i++) {
|
|
384
|
+
heap_reorder<C>(k, distances + i * k, labels + i * k);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
} // anonymous namespace
|
|
389
|
+
|
|
390
|
+
// --- Entry points ---
|
|
391
|
+
|
|
392
|
+
template <>
|
|
393
|
+
BinaryInvertedListScanner* make_binary_ivf_scanner_fixSL<THE_SIMD_LEVEL>(
|
|
394
|
+
size_t code_size,
|
|
395
|
+
bool store_pairs) {
|
|
396
|
+
return with_HammingComputer<THE_SIMD_LEVEL>(
|
|
397
|
+
code_size,
|
|
398
|
+
[&]<class HammingComputer>() -> BinaryInvertedListScanner* {
|
|
399
|
+
return new IVFBinaryScannerL2<HammingComputer>(
|
|
400
|
+
code_size, store_pairs);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
template <>
|
|
405
|
+
void search_knn_hamming_per_invlist_fixSL<THE_SIMD_LEVEL>(
|
|
406
|
+
int code_size,
|
|
407
|
+
const IndexBinaryIVF* ivf,
|
|
408
|
+
size_t n,
|
|
409
|
+
const uint8_t* x,
|
|
410
|
+
idx_t k,
|
|
411
|
+
const idx_t* keys_in,
|
|
412
|
+
const int32_t* coarse_dis,
|
|
413
|
+
int32_t* distances,
|
|
414
|
+
idx_t* labels,
|
|
415
|
+
bool store_pairs,
|
|
416
|
+
const IVFSearchParameters* params) {
|
|
417
|
+
with_HammingComputer<THE_SIMD_LEVEL>(
|
|
418
|
+
code_size, [&]<class HammingComputer>() {
|
|
419
|
+
search_knn_hamming_per_invlist<HammingComputer>(
|
|
420
|
+
ivf,
|
|
421
|
+
n,
|
|
422
|
+
x,
|
|
423
|
+
k,
|
|
424
|
+
keys_in,
|
|
425
|
+
coarse_dis,
|
|
426
|
+
distances,
|
|
427
|
+
labels,
|
|
428
|
+
store_pairs,
|
|
429
|
+
params);
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
template <>
|
|
434
|
+
void search_knn_hamming_count_fixSL<THE_SIMD_LEVEL>(
|
|
435
|
+
int code_size,
|
|
436
|
+
bool store_pairs,
|
|
437
|
+
const IndexBinaryIVF* ivf,
|
|
438
|
+
size_t nx,
|
|
439
|
+
const uint8_t* x,
|
|
440
|
+
const idx_t* keys,
|
|
441
|
+
int k,
|
|
442
|
+
int32_t* distances,
|
|
443
|
+
idx_t* labels,
|
|
444
|
+
const IVFSearchParameters* params) {
|
|
445
|
+
if (store_pairs) {
|
|
446
|
+
with_HammingComputer<THE_SIMD_LEVEL>(
|
|
447
|
+
code_size, [&]<class HammingComputer>() {
|
|
448
|
+
search_knn_hamming_count<HammingComputer, true>(
|
|
449
|
+
ivf, nx, x, keys, k, distances, labels, params);
|
|
450
|
+
});
|
|
451
|
+
} else {
|
|
452
|
+
with_HammingComputer<THE_SIMD_LEVEL>(
|
|
453
|
+
code_size, [&]<class HammingComputer>() {
|
|
454
|
+
search_knn_hamming_count<HammingComputer, false>(
|
|
455
|
+
ivf, nx, x, keys, k, distances, labels, params);
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
} // namespace faiss
|
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
/*
|
|
9
|
+
* Per-ISA implementation of Hamming distance computation for
|
|
10
|
+
* IndexIVFSpectralHash. Included once per SIMD TU with THE_SIMD_LEVEL
|
|
11
|
+
* set to the desired SIMDLevel.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#pragma once
|
|
15
|
+
|
|
16
|
+
#ifndef THE_SIMD_LEVEL
|
|
17
|
+
#error "THE_SIMD_LEVEL must be defined before including this file"
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
#include <faiss/utils/hamming_distance/hamming_computer.h>
|
|
21
|
+
|
|
22
|
+
#include <cmath>
|
|
23
|
+
#include <cstring>
|
|
24
|
+
|
|
25
|
+
#include <faiss/IndexIVFSpectralHash.h>
|
|
26
|
+
#include <faiss/VectorTransform.h>
|
|
27
|
+
#include <faiss/impl/AuxIndexStructures.h>
|
|
28
|
+
#include <faiss/impl/FaissAssert.h>
|
|
29
|
+
#include <faiss/impl/ResultHandler.h>
|
|
30
|
+
#include <faiss/impl/binary_hamming/dispatch.h>
|
|
31
|
+
#include <faiss/utils/hamming.h>
|
|
32
|
+
|
|
33
|
+
namespace faiss {
|
|
34
|
+
|
|
35
|
+
namespace {
|
|
36
|
+
|
|
37
|
+
void binarize_with_freq_impl(
|
|
38
|
+
size_t nbit,
|
|
39
|
+
float freq,
|
|
40
|
+
const float* x,
|
|
41
|
+
const float* c,
|
|
42
|
+
uint8_t* codes) {
|
|
43
|
+
memset(codes, 0, (nbit + 7) / 8);
|
|
44
|
+
for (size_t i = 0; i < nbit; i++) {
|
|
45
|
+
float xf = (x[i] - c[i]);
|
|
46
|
+
int64_t xi = int64_t(std::floor(xf * freq));
|
|
47
|
+
int64_t bit = xi & 1;
|
|
48
|
+
codes[i >> 3] |= bit << (i & 7);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
template <class HammingComputer>
|
|
53
|
+
struct IVFScanner : InvertedListScanner {
|
|
54
|
+
using InvertedListScanner::scan_codes;
|
|
55
|
+
const IndexIVFSpectralHash* index;
|
|
56
|
+
size_t nbit;
|
|
57
|
+
|
|
58
|
+
float period, freq;
|
|
59
|
+
std::vector<float> q;
|
|
60
|
+
std::vector<float> zero;
|
|
61
|
+
std::vector<uint8_t> qcode;
|
|
62
|
+
HammingComputer hc;
|
|
63
|
+
|
|
64
|
+
IVFScanner(const IndexIVFSpectralHash* index_in, bool store_pairs_in)
|
|
65
|
+
: index(index_in),
|
|
66
|
+
nbit(index_in->nbit),
|
|
67
|
+
period(index_in->period),
|
|
68
|
+
freq(2.0 / index_in->period),
|
|
69
|
+
q(nbit),
|
|
70
|
+
zero(nbit),
|
|
71
|
+
qcode(index_in->code_size),
|
|
72
|
+
hc(qcode.data(), static_cast<int>(index_in->code_size)) {
|
|
73
|
+
this->store_pairs = store_pairs_in;
|
|
74
|
+
this->code_size = index->code_size;
|
|
75
|
+
this->keep_max = is_similarity_metric(index->metric_type);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
void set_query(const float* query) override {
|
|
79
|
+
FAISS_THROW_IF_NOT(query);
|
|
80
|
+
FAISS_THROW_IF_NOT(q.size() == static_cast<size_t>(nbit));
|
|
81
|
+
index->vt->apply_noalloc(1, query, q.data());
|
|
82
|
+
|
|
83
|
+
if (index->threshold_type == IndexIVFSpectralHash::Thresh_global) {
|
|
84
|
+
binarize_with_freq_impl(
|
|
85
|
+
nbit, freq, q.data(), zero.data(), qcode.data());
|
|
86
|
+
hc.set(qcode.data(), code_size);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
void set_list(idx_t list_no_in, float /*coarse_dis*/) override {
|
|
91
|
+
this->list_no = list_no_in;
|
|
92
|
+
if (index->threshold_type != IndexIVFSpectralHash::Thresh_global) {
|
|
93
|
+
const float* c = index->trained.data() + list_no_in * nbit;
|
|
94
|
+
binarize_with_freq_impl(nbit, freq, q.data(), c, qcode.data());
|
|
95
|
+
hc.set(qcode.data(), code_size);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
float distance_to_code(const uint8_t* code) const final {
|
|
100
|
+
return hc.hamming(code);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
size_t scan_codes(
|
|
104
|
+
size_t list_size,
|
|
105
|
+
const uint8_t* codes,
|
|
106
|
+
const idx_t* ids,
|
|
107
|
+
ResultHandler& handler) const override {
|
|
108
|
+
size_t nup = 0;
|
|
109
|
+
// get_InvertedListScanner asserts no IDSelector, so every code
|
|
110
|
+
// in the list has its distance computed.
|
|
111
|
+
for (size_t j = 0; j < list_size; j++) {
|
|
112
|
+
float dis = hc.hamming(codes);
|
|
113
|
+
handler.stats.scan_cnt++;
|
|
114
|
+
|
|
115
|
+
if (dis < handler.threshold) {
|
|
116
|
+
int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
117
|
+
if (handler.add_result(dis, id)) {
|
|
118
|
+
handler.stats.nheap_updates++;
|
|
119
|
+
nup++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
codes += code_size;
|
|
123
|
+
}
|
|
124
|
+
return nup;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
void scan_codes_range(
|
|
128
|
+
size_t list_size,
|
|
129
|
+
const uint8_t* codes,
|
|
130
|
+
const idx_t* ids,
|
|
131
|
+
float radius,
|
|
132
|
+
RangeQueryResult& result) const override {
|
|
133
|
+
for (size_t j = 0; j < list_size; j++) {
|
|
134
|
+
float dis = hc.hamming(codes);
|
|
135
|
+
result.stats.scan_cnt++;
|
|
136
|
+
if (dis < radius) {
|
|
137
|
+
int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
138
|
+
result.add(dis, id);
|
|
139
|
+
result.stats.nheap_updates++;
|
|
140
|
+
}
|
|
141
|
+
codes += code_size;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
} // anonymous namespace
|
|
147
|
+
|
|
148
|
+
template <>
|
|
149
|
+
InvertedListScanner* make_spectral_hash_scanner_fixSL<THE_SIMD_LEVEL>(
|
|
150
|
+
int code_size,
|
|
151
|
+
const IndexIVFSpectralHash* index,
|
|
152
|
+
bool store_pairs) {
|
|
153
|
+
return with_HammingComputer<THE_SIMD_LEVEL>(
|
|
154
|
+
code_size, [&]<class HammingComputer>() -> InvertedListScanner* {
|
|
155
|
+
return new IVFScanner<HammingComputer>(index, store_pairs);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
} // namespace faiss
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
/*
|
|
9
|
+
* Per-ISA implementation of polysemous Hamming inner loop for IndexPQ.
|
|
10
|
+
* Included once per SIMD TU with THE_SIMD_LEVEL set to the desired
|
|
11
|
+
* SIMDLevel.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#pragma once
|
|
15
|
+
|
|
16
|
+
#ifndef THE_SIMD_LEVEL
|
|
17
|
+
#error "THE_SIMD_LEVEL must be defined before including this file"
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
#include <faiss/utils/hamming_distance/hamming_computer.h>
|
|
21
|
+
|
|
22
|
+
#include <faiss/IndexPQ.h>
|
|
23
|
+
#include <faiss/impl/binary_hamming/dispatch.h>
|
|
24
|
+
#include <faiss/utils/Heap.h>
|
|
25
|
+
#include <faiss/utils/hamming.h>
|
|
26
|
+
|
|
27
|
+
namespace faiss {
|
|
28
|
+
|
|
29
|
+
namespace {
|
|
30
|
+
|
|
31
|
+
template <class HammingComputer>
|
|
32
|
+
size_t polysemous_inner_loop(
|
|
33
|
+
const IndexPQ* index,
|
|
34
|
+
const float* dis_table_qi,
|
|
35
|
+
const uint8_t* q_code,
|
|
36
|
+
size_t k,
|
|
37
|
+
float* heap_dis,
|
|
38
|
+
int64_t* heap_ids,
|
|
39
|
+
int ht) {
|
|
40
|
+
size_t M = index->pq.M;
|
|
41
|
+
size_t code_size = index->pq.code_size;
|
|
42
|
+
size_t ksub = index->pq.ksub;
|
|
43
|
+
size_t ntotal = index->ntotal;
|
|
44
|
+
|
|
45
|
+
const uint8_t* b_code = index->codes.data();
|
|
46
|
+
|
|
47
|
+
size_t n_pass_i = 0;
|
|
48
|
+
|
|
49
|
+
HammingComputer hc(q_code, static_cast<int>(code_size));
|
|
50
|
+
|
|
51
|
+
for (int64_t bi = 0; bi < static_cast<int64_t>(ntotal); bi++) {
|
|
52
|
+
int hd = hc.hamming(b_code);
|
|
53
|
+
|
|
54
|
+
if (hd < ht) {
|
|
55
|
+
n_pass_i++;
|
|
56
|
+
|
|
57
|
+
float dis = 0;
|
|
58
|
+
const float* dis_table = dis_table_qi;
|
|
59
|
+
for (size_t m = 0; m < M; m++) {
|
|
60
|
+
dis += dis_table[b_code[m]];
|
|
61
|
+
dis_table += ksub;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (dis < heap_dis[0]) {
|
|
65
|
+
maxheap_replace_top(k, heap_dis, heap_ids, dis, bi);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
b_code += code_size;
|
|
69
|
+
}
|
|
70
|
+
return n_pass_i;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
} // anonymous namespace
|
|
74
|
+
|
|
75
|
+
template <>
|
|
76
|
+
size_t polysemous_inner_loop_fixSL<THE_SIMD_LEVEL>(
|
|
77
|
+
int code_size,
|
|
78
|
+
const IndexPQ* index,
|
|
79
|
+
const float* dis_table_qi,
|
|
80
|
+
const uint8_t* q_code,
|
|
81
|
+
size_t k,
|
|
82
|
+
float* heap_dis,
|
|
83
|
+
int64_t* heap_ids,
|
|
84
|
+
int ht) {
|
|
85
|
+
return with_HammingComputer<THE_SIMD_LEVEL>(
|
|
86
|
+
code_size, [&]<class HammingComputer>() -> size_t {
|
|
87
|
+
return polysemous_inner_loop<HammingComputer>(
|
|
88
|
+
index, dis_table_qi, q_code, k, heap_dis, heap_ids, ht);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
} // namespace faiss
|