faiss 0.6.4 → 0.6.5
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 +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +175 -0
- data/vendor/faiss/faiss/Clustering.cpp +150 -60
- data/vendor/faiss/faiss/Clustering.h +29 -0
- data/vendor/faiss/faiss/IVFlib.cpp +99 -0
- data/vendor/faiss/faiss/IVFlib.h +15 -0
- data/vendor/faiss/faiss/Index.cpp +44 -0
- data/vendor/faiss/faiss/Index.h +19 -14
- data/vendor/faiss/faiss/IndexBinary.cpp +8 -0
- data/vendor/faiss/faiss/IndexBinary.h +8 -0
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +82 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +19 -0
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +34 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +33 -17
- data/vendor/faiss/faiss/IndexFastScan.h +6 -3
- data/vendor/faiss/faiss/IndexFlat.cpp +56 -0
- data/vendor/faiss/faiss/IndexFlat.h +31 -0
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +6 -1
- data/vendor/faiss/faiss/IndexHNSW.cpp +456 -10
- data/vendor/faiss/faiss/IndexHNSW.h +38 -0
- data/vendor/faiss/faiss/IndexIDMap.cpp +32 -0
- data/vendor/faiss/faiss/IndexIDMap.h +7 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +281 -31
- data/vendor/faiss/faiss/IndexIVF.h +53 -1
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +46 -14
- data/vendor/faiss/faiss/IndexIVFFastScan.h +4 -2
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +33 -0
- data/vendor/faiss/faiss/IndexIVFFlat.h +16 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1 -0
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +3 -20
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +50 -14
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -2
- data/vendor/faiss/faiss/IndexIVFSQFastScan.cpp +855 -0
- data/vendor/faiss/faiss/IndexIVFSQFastScan.h +145 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -3
- data/vendor/faiss/faiss/IndexPiPNN.cpp +201 -0
- data/vendor/faiss/faiss/IndexPiPNN.h +83 -0
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +6 -3
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +10 -4
- data/vendor/faiss/faiss/IndexReplicas.cpp +20 -0
- data/vendor/faiss/faiss/IndexReplicas.h +9 -0
- data/vendor/faiss/faiss/IndexSQFastScan.cpp +648 -0
- data/vendor/faiss/faiss/IndexSQFastScan.h +129 -0
- data/vendor/faiss/faiss/IndexShards.cpp +10 -0
- data/vendor/faiss/faiss/IndexShards.h +5 -0
- data/vendor/faiss/faiss/SuperKMeans.cpp +57 -15
- data/vendor/faiss/faiss/SuperKMeans.h +9 -4
- data/vendor/faiss/faiss/VectorTransform.cpp +3 -2
- data/vendor/faiss/faiss/clone_index.cpp +24 -0
- data/vendor/faiss/faiss/gpu/Dataset.h +112 -0
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +16 -13
- data/vendor/faiss/faiss/gpu/GpuCloner.h +4 -0
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -0
- data/vendor/faiss/faiss/gpu/GpuIndex.h +4 -13
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +26 -13
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +45 -22
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuDatasetHeader.cpp +18 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +215 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +98 -0
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +11 -0
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -1
- data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +11 -0
- data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +92 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +4 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexBinaryFlat.h +69 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +38 -0
- data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +106 -0
- data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +10 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +2 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +1 -6
- data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +134 -45
- data/vendor/faiss/faiss/impl/ClusteringHelpers.h +36 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +286 -136
- data/vendor/faiss/faiss/impl/DistanceComputer.cpp +63 -0
- data/vendor/faiss/faiss/impl/DistanceComputer.h +3 -29
- data/vendor/faiss/faiss/impl/HNSW.cpp +46 -10
- data/vendor/faiss/faiss/impl/HNSW.h +72 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +6 -19
- data/vendor/faiss/faiss/impl/NNDescent.cpp +2 -1
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -2
- data/vendor/faiss/faiss/impl/Panorama.h +3 -2
- data/vendor/faiss/faiss/impl/PiPNN.cpp +822 -0
- data/vendor/faiss/faiss/impl/PiPNN.h +122 -0
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +54 -11
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +1 -1
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +81 -57
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +15 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -6
- data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +5 -2
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +0 -4
- data/vendor/faiss/faiss/impl/expanded_scanners.h +88 -0
- data/vendor/faiss/faiss/impl/fast_scan/FastScanDistancePostProcessing.h +4 -0
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +61 -64
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +13 -14
- data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +17 -129
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +25 -19
- data/vendor/faiss/faiss/impl/fast_scan/fast_scan.cpp +5 -0
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +0 -88
- data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/kernels_neon.h +155 -0
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +22 -1
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd512.h +3 -2
- data/vendor/faiss/faiss/impl/fast_scan/simd_result_handlers.h +41 -23
- data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/index_read.cpp +172 -0
- data/vendor/faiss/faiss/impl/index_write.cpp +95 -0
- data/vendor/faiss/faiss/impl/pipnn/HashPrune.cpp +159 -0
- data/vendor/faiss/faiss/impl/pipnn/HashPrune.h +69 -0
- data/vendor/faiss/faiss/impl/pipnn/Partition.cpp +587 -0
- data/vendor/faiss/faiss/impl/pipnn/Partition.h +93 -0
- data/vendor/faiss/faiss/impl/pipnn/kernels.cpp +326 -0
- data/vendor/faiss/faiss/impl/pipnn/kernels.h +92 -0
- data/vendor/faiss/faiss/impl/platform_macros.h +45 -0
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +79 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +6 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx2.h +4 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx512.h +4 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +19 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +6 -6
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +131 -6
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_rvv_kernel.h +89 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +21 -10
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +45 -18
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +2 -1
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +5 -1
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +28 -52
- data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +59 -11
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +226 -77
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +482 -103
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +2 -149
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +3 -698
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +66 -57
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +101 -96
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +3185 -144
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_coefficients.h +48 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_rvv_kernel.h +546 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +2 -2
- data/vendor/faiss/faiss/impl/simd_dispatch.h +7 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_avx2.h +14 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +7 -8
- data/vendor/faiss/faiss/impl/sq_fastscan_utils.h +232 -0
- data/vendor/faiss/faiss/index_factory.cpp +76 -0
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +3 -2
- data/vendor/faiss/faiss/utils/AlignedTable.h +6 -1
- data/vendor/faiss/faiss/utils/Heap.cpp +4 -3
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +16 -5
- data/vendor/faiss/faiss/utils/bf16.h +36 -0
- data/vendor/faiss/faiss/utils/distances.cpp +226 -15
- data/vendor/faiss/faiss/utils/distances.h +34 -0
- data/vendor/faiss/faiss/utils/distances_dispatch.h +6 -4
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +2 -5
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +0 -14
- data/vendor/faiss/faiss/utils/distances_fused/rvv.cpp +25 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +0 -4
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +2 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +9 -0
- data/vendor/faiss/faiss/utils/fp16-fp16c.h +4 -0
- data/vendor/faiss/faiss/utils/fp16-inl.h +26 -52
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +33 -5
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_vpopcnt.h +15 -30
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +2 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +0 -4
- data/vendor/faiss/faiss/utils/pq_code_distance.h +8 -4
- data/vendor/faiss/faiss/utils/prefetch.h +1 -26
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +26 -27
- data/vendor/faiss/faiss/utils/quantize_lut.h +11 -0
- data/vendor/faiss/faiss/utils/rabitq_simd.h +51 -16
- data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +9 -4
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +37 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +64 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +64 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +353 -71
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv_kernel.h +68 -0
- data/vendor/faiss/faiss/utils/simd_impl/exhaustive_L2sqr_blas_cmax.h +93 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels.h +76 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx2.cpp +52 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx512.cpp +52 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_neon.cpp +48 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx2.h +44 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx512.h +43 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum.h +38 -0
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +54 -15
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +38 -21
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_vpopcnt.cpp +51 -14
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +297 -10
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_levels.cpp +19 -3
- data/vendor/faiss/faiss/utils/simd_levels.h +74 -1
- data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +0 -4
- data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +0 -4
- data/vendor/faiss/faiss/utils/utils.cpp +80 -0
- data/vendor/faiss/faiss/utils/utils.h +24 -0
- metadata +33 -1
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
#include <faiss/impl/fast_scan/FastScanDistancePostProcessing.h>
|
|
22
22
|
#include <faiss/impl/fast_scan/fast_scan.h>
|
|
23
23
|
#include <faiss/impl/fast_scan/simd_result_handlers.h>
|
|
24
|
+
#include <faiss/impl/platform_macros.h>
|
|
24
25
|
#include <faiss/invlists/BlockInvertedLists.h>
|
|
25
26
|
#include <faiss/utils/hamming.h>
|
|
26
27
|
#include <faiss/utils/quantize_lut.h>
|
|
@@ -646,8 +647,23 @@ void IndexIVFFastScan::search_dispatch_implem(
|
|
|
646
647
|
search_implem_14(
|
|
647
648
|
n, x, k, distances, labels, cq, impl, context, params);
|
|
648
649
|
} else {
|
|
650
|
+
// Size each thread's LUT here, on the calling thread: a
|
|
651
|
+
// heap-profiler sample taken on an OpenMP worker unwinds
|
|
652
|
+
// through libomp, which is very slow on aarch64. The tables
|
|
653
|
+
// keep their capacity, so smaller slices do not reallocate.
|
|
654
|
+
std::vector<AlignedTable<uint8_t>> thread_dis_tables(
|
|
655
|
+
omp_get_max_threads());
|
|
656
|
+
const size_t max_slice_n = (n + nslice - 1) / nslice;
|
|
657
|
+
const size_t lut_per_query =
|
|
658
|
+
ksub * M2 * (lookup_table_is_3d() ? cur_nprobe : 1);
|
|
659
|
+
for (auto& t : thread_dis_tables) {
|
|
660
|
+
t.keep_capacity = true;
|
|
661
|
+
t.resize(max_slice_n * lut_per_query);
|
|
662
|
+
}
|
|
649
663
|
#pragma omp parallel for reduction(+ : ndis, nlist_visited)
|
|
650
664
|
for (int slice = 0; slice < nslice; slice++) {
|
|
665
|
+
AlignedTable<uint8_t>* dis_tables_buf =
|
|
666
|
+
&thread_dis_tables.at(omp_get_thread_num());
|
|
651
667
|
idx_t i0 = n * slice / nslice;
|
|
652
668
|
idx_t i1 = n * (slice + 1) / nslice;
|
|
653
669
|
float* dis_i = distances + i0 * k;
|
|
@@ -663,6 +679,9 @@ void IndexIVFFastScan::search_dispatch_implem(
|
|
|
663
679
|
if (thread_context.query_factors != nullptr) {
|
|
664
680
|
thread_context.query_factors += i0 * cur_nprobe;
|
|
665
681
|
}
|
|
682
|
+
if (thread_context.rotated_q != nullptr) {
|
|
683
|
+
thread_context.rotated_q += i0 * cur_nprobe * d;
|
|
684
|
+
}
|
|
666
685
|
|
|
667
686
|
auto scanner = make_knn_scanner(
|
|
668
687
|
is_max,
|
|
@@ -684,7 +703,8 @@ void IndexIVFFastScan::search_dispatch_implem(
|
|
|
684
703
|
&nlist_visited,
|
|
685
704
|
thread_context,
|
|
686
705
|
params,
|
|
687
|
-
*scanner
|
|
706
|
+
*scanner,
|
|
707
|
+
dis_tables_buf);
|
|
688
708
|
} else {
|
|
689
709
|
search_implem_10(
|
|
690
710
|
i1 - i0,
|
|
@@ -696,7 +716,8 @@ void IndexIVFFastScan::search_dispatch_implem(
|
|
|
696
716
|
&nlist_visited,
|
|
697
717
|
thread_context,
|
|
698
718
|
params,
|
|
699
|
-
*scanner
|
|
719
|
+
*scanner,
|
|
720
|
+
dis_tables_buf);
|
|
700
721
|
}
|
|
701
722
|
}
|
|
702
723
|
}
|
|
@@ -1020,9 +1041,12 @@ void IndexIVFFastScan::search_implem_10(
|
|
|
1020
1041
|
size_t* nlist_out,
|
|
1021
1042
|
const FastScanDistancePostProcessing& context,
|
|
1022
1043
|
const IVFSearchParameters* params,
|
|
1023
|
-
FastScanCodeScanner& scanner
|
|
1044
|
+
FastScanCodeScanner& scanner,
|
|
1045
|
+
AlignedTable<uint8_t>* dis_tables_buf) const {
|
|
1024
1046
|
size_t dim12 = ksub * M2;
|
|
1025
|
-
AlignedTable<uint8_t>
|
|
1047
|
+
AlignedTable<uint8_t> local_dis_tables;
|
|
1048
|
+
AlignedTable<uint8_t>& dis_tables =
|
|
1049
|
+
dis_tables_buf ? *dis_tables_buf : local_dis_tables;
|
|
1026
1050
|
AlignedTable<uint16_t> biases;
|
|
1027
1051
|
std::unique_ptr<float[]> normalizers(new float[2 * n]);
|
|
1028
1052
|
|
|
@@ -1060,6 +1084,7 @@ void IndexIVFFastScan::search_implem_10(
|
|
|
1060
1084
|
// Allocate probe_map once and reuse it
|
|
1061
1085
|
std::vector<int> probe_map;
|
|
1062
1086
|
probe_map.reserve(1);
|
|
1087
|
+
const size_t block_stride = get_block_stride();
|
|
1063
1088
|
|
|
1064
1089
|
for (idx_t i = 0; i < n; i++) {
|
|
1065
1090
|
const uint8_t* LUT = nullptr;
|
|
@@ -1134,7 +1159,7 @@ void IndexIVFFastScan::search_implem_10(
|
|
|
1134
1159
|
codes.get(),
|
|
1135
1160
|
LUT,
|
|
1136
1161
|
context.pq2x4_scale,
|
|
1137
|
-
|
|
1162
|
+
block_stride);
|
|
1138
1163
|
|
|
1139
1164
|
ndis += ls;
|
|
1140
1165
|
nlist_visited++;
|
|
@@ -1172,14 +1197,17 @@ void IndexIVFFastScan::search_implem_12(
|
|
|
1172
1197
|
size_t* nlist_out,
|
|
1173
1198
|
const FastScanDistancePostProcessing& context,
|
|
1174
1199
|
const IVFSearchParameters* /* params */,
|
|
1175
|
-
FastScanCodeScanner& scanner
|
|
1200
|
+
FastScanCodeScanner& scanner,
|
|
1201
|
+
AlignedTable<uint8_t>* dis_tables_buf) const {
|
|
1176
1202
|
if (n == 0) { // does not work well with reservoir
|
|
1177
1203
|
return;
|
|
1178
1204
|
}
|
|
1179
1205
|
FAISS_THROW_IF_NOT(bbs == 32);
|
|
1180
1206
|
|
|
1181
1207
|
size_t dim12 = ksub * M2;
|
|
1182
|
-
AlignedTable<uint8_t>
|
|
1208
|
+
AlignedTable<uint8_t> local_dis_tables;
|
|
1209
|
+
AlignedTable<uint8_t>& dis_tables =
|
|
1210
|
+
dis_tables_buf ? *dis_tables_buf : local_dis_tables;
|
|
1183
1211
|
AlignedTable<uint16_t> biases;
|
|
1184
1212
|
std::unique_ptr<float[]> normalizers(new float[2 * n]);
|
|
1185
1213
|
|
|
@@ -1196,6 +1224,7 @@ void IndexIVFFastScan::search_implem_12(
|
|
|
1196
1224
|
size_t cur_nprobe = cq.nprobe;
|
|
1197
1225
|
|
|
1198
1226
|
std::vector<QC> qcs;
|
|
1227
|
+
qcs.reserve(n * cur_nprobe);
|
|
1199
1228
|
{
|
|
1200
1229
|
size_t ij = 0;
|
|
1201
1230
|
for (idx_t i = 0; i < n; i++) {
|
|
@@ -1226,6 +1255,9 @@ void IndexIVFFastScan::search_implem_12(
|
|
|
1226
1255
|
// Allocate vectors once and reuse them
|
|
1227
1256
|
std::vector<int> probe_map;
|
|
1228
1257
|
probe_map.reserve(actual_qbs2);
|
|
1258
|
+
std::vector<int> q_map(actual_qbs2), lut_entries(actual_qbs2);
|
|
1259
|
+
AlignedTable<uint8_t> LUT(actual_qbs2 * dim12);
|
|
1260
|
+
const size_t block_stride = get_block_stride();
|
|
1229
1261
|
|
|
1230
1262
|
size_t i0 = 0;
|
|
1231
1263
|
uint64_t t_copy_pack = 0, t_scan = 0;
|
|
@@ -1252,8 +1284,6 @@ void IndexIVFFastScan::search_implem_12(
|
|
|
1252
1284
|
// re-organize LUTs and biases into the right order
|
|
1253
1285
|
int nc = static_cast<int>(i1 - i0);
|
|
1254
1286
|
|
|
1255
|
-
std::vector<int> q_map(nc), lut_entries(nc);
|
|
1256
|
-
AlignedTable<uint8_t> LUT(nc * dim12);
|
|
1257
1287
|
memset(LUT.get(), -1, nc * dim12);
|
|
1258
1288
|
int qbs_for_list = pq4_preferred_qbs(nc);
|
|
1259
1289
|
|
|
@@ -1303,7 +1333,7 @@ void IndexIVFFastScan::search_implem_12(
|
|
|
1303
1333
|
codes.get(),
|
|
1304
1334
|
LUT.get(),
|
|
1305
1335
|
context.pq2x4_scale,
|
|
1306
|
-
|
|
1336
|
+
block_stride);
|
|
1307
1337
|
// prepare for next loop
|
|
1308
1338
|
i0 = i1;
|
|
1309
1339
|
}
|
|
@@ -1351,6 +1381,7 @@ void IndexIVFFastScan::search_implem_14(
|
|
|
1351
1381
|
size_t cur_nprobe = cq.nprobe;
|
|
1352
1382
|
|
|
1353
1383
|
std::vector<QC> qcs;
|
|
1384
|
+
qcs.reserve(n * cur_nprobe);
|
|
1354
1385
|
{
|
|
1355
1386
|
size_t ij = 0;
|
|
1356
1387
|
for (idx_t i = 0; i < n; i++) {
|
|
@@ -1461,8 +1492,11 @@ void IndexIVFFastScan::search_implem_14(
|
|
|
1461
1492
|
// Allocate probe_map once per thread and reuse it
|
|
1462
1493
|
std::vector<int> probe_map;
|
|
1463
1494
|
probe_map.reserve(actual_qbs2);
|
|
1495
|
+
std::vector<int> q_map(actual_qbs2), lut_entries(actual_qbs2);
|
|
1496
|
+
AlignedTable<uint8_t> LUT(actual_qbs2 * dim12);
|
|
1497
|
+
const size_t block_stride = get_block_stride();
|
|
1464
1498
|
|
|
1465
|
-
#pragma omp for schedule(
|
|
1499
|
+
#pragma omp for schedule(FAISS_OMP_DYNAMIC)
|
|
1466
1500
|
for (idx_t cluster = 0; cluster < static_cast<idx_t>(ses.size());
|
|
1467
1501
|
cluster++) {
|
|
1468
1502
|
size_t i0 = ses[cluster].start;
|
|
@@ -1474,8 +1508,6 @@ void IndexIVFFastScan::search_implem_14(
|
|
|
1474
1508
|
// re-organize LUTs and biases into the right order
|
|
1475
1509
|
int nc = static_cast<int>(i1 - i0);
|
|
1476
1510
|
|
|
1477
|
-
std::vector<int> q_map(nc), lut_entries(nc);
|
|
1478
|
-
AlignedTable<uint8_t> LUT(nc * dim12);
|
|
1479
1511
|
memset(LUT.get(), -1, nc * dim12);
|
|
1480
1512
|
int qbs_for_list = pq4_preferred_qbs(nc);
|
|
1481
1513
|
|
|
@@ -1526,7 +1558,7 @@ void IndexIVFFastScan::search_implem_14(
|
|
|
1526
1558
|
codes.get(),
|
|
1527
1559
|
LUT.get(),
|
|
1528
1560
|
context.pq2x4_scale,
|
|
1529
|
-
|
|
1561
|
+
block_stride);
|
|
1530
1562
|
}
|
|
1531
1563
|
|
|
1532
1564
|
// labels is in-place for HeapHC
|
|
@@ -303,7 +303,8 @@ struct IndexIVFFastScan : IndexIVF {
|
|
|
303
303
|
size_t* nlist_out,
|
|
304
304
|
const FastScanDistancePostProcessing& context,
|
|
305
305
|
const IVFSearchParameters* params,
|
|
306
|
-
FastScanCodeScanner& scanner
|
|
306
|
+
FastScanCodeScanner& scanner,
|
|
307
|
+
AlignedTable<uint8_t>* dis_tables_buf = nullptr) const;
|
|
307
308
|
|
|
308
309
|
void search_implem_12(
|
|
309
310
|
idx_t n,
|
|
@@ -314,7 +315,8 @@ struct IndexIVFFastScan : IndexIVF {
|
|
|
314
315
|
size_t* nlist_out,
|
|
315
316
|
const FastScanDistancePostProcessing& context,
|
|
316
317
|
const IVFSearchParameters* params,
|
|
317
|
-
FastScanCodeScanner& scanner
|
|
318
|
+
FastScanCodeScanner& scanner,
|
|
319
|
+
AlignedTable<uint8_t>* dis_tables_buf = nullptr) const;
|
|
318
320
|
|
|
319
321
|
// implem 14 is multithreaded internally across nprobes and queries
|
|
320
322
|
void search_implem_14(
|
|
@@ -57,6 +57,25 @@ IndexIVFFlat::IndexIVFFlat() {
|
|
|
57
57
|
by_residual = false;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
void IndexIVFFlat::train_encoded(
|
|
61
|
+
idx_t n,
|
|
62
|
+
const uint8_t* x,
|
|
63
|
+
const Index* codec) {
|
|
64
|
+
FAISS_THROW_IF_NOT_MSG(codec, "encoded training requires a codec");
|
|
65
|
+
train_q1_encoded(n, x, codec, verbose, metric_type);
|
|
66
|
+
is_trained = true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
void IndexIVFFlat::train_ex(idx_t n, const void* x, NumericType numeric_type) {
|
|
70
|
+
if (numeric_type != NumericType::Float16) {
|
|
71
|
+
IndexIVF::train_ex(n, x, numeric_type);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
FAISS_THROW_IF_NOT_MSG(x, "training data must not be null");
|
|
75
|
+
train_q1_ex(n, x, numeric_type, verbose, metric_type);
|
|
76
|
+
is_trained = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
60
79
|
void IndexIVFFlat::add_core(
|
|
61
80
|
idx_t n,
|
|
62
81
|
const float* x,
|
|
@@ -186,6 +205,20 @@ IndexIVFFlatDedup::IndexIVFFlatDedup(
|
|
|
186
205
|
metric_type_in,
|
|
187
206
|
own_invlists_in) {}
|
|
188
207
|
|
|
208
|
+
void IndexIVFFlatDedup::train_encoded(idx_t, const uint8_t*, const Index*) {
|
|
209
|
+
FAISS_THROW_MSG("encoded training is not supported by IndexIVFFlatDedup");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
void IndexIVFFlatDedup::train_ex(
|
|
213
|
+
idx_t n,
|
|
214
|
+
const void* x,
|
|
215
|
+
NumericType numeric_type) {
|
|
216
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
217
|
+
numeric_type == NumericType::Float32,
|
|
218
|
+
"only fp32 training is supported by IndexIVFFlatDedup");
|
|
219
|
+
train(n, static_cast<const float*>(x));
|
|
220
|
+
}
|
|
221
|
+
|
|
189
222
|
void IndexIVFFlatDedup::train(idx_t n, const float* x) {
|
|
190
223
|
std::unordered_map<uint64_t, idx_t> map;
|
|
191
224
|
std::unique_ptr<float[]> x2(new float[n * d]);
|
|
@@ -29,6 +29,16 @@ struct IndexIVFFlat : IndexIVF {
|
|
|
29
29
|
MetricType = METRIC_L2,
|
|
30
30
|
bool own_invlists = true);
|
|
31
31
|
|
|
32
|
+
/** Train the coarse quantizer from vectors decoded on demand by `codec`.
|
|
33
|
+
*
|
|
34
|
+
* IndexIVFFlat has no trainable residual encoder, so this avoids a
|
|
35
|
+
* corpus-sized decoded buffer. The codec must remain alive for this call.
|
|
36
|
+
*/
|
|
37
|
+
void train_encoded(idx_t n, const uint8_t* x, const Index* codec) override;
|
|
38
|
+
|
|
39
|
+
/// Float16 trains only the coarse quantizer, natively on the fp16 rows.
|
|
40
|
+
void train_ex(idx_t n, const void* x, NumericType numeric_type) override;
|
|
41
|
+
|
|
32
42
|
void add_core(
|
|
33
43
|
idx_t n,
|
|
34
44
|
const float* x,
|
|
@@ -110,6 +120,12 @@ struct IndexIVFFlatDedup : IndexIVFFlat {
|
|
|
110
120
|
/// also dedups the training set
|
|
111
121
|
void train(idx_t n, const float* x) override;
|
|
112
122
|
|
|
123
|
+
/// Encoded training cannot preserve the byte-exact deduplication contract.
|
|
124
|
+
void train_encoded(idx_t n, const uint8_t* x, const Index* codec) override;
|
|
125
|
+
|
|
126
|
+
/// Non-fp32 input is rejected for the same reason as train_encoded.
|
|
127
|
+
void train_ex(idx_t n, const void* x, NumericType numeric_type) override;
|
|
128
|
+
|
|
113
129
|
/// implemented for all IndexIVF* classes
|
|
114
130
|
void add_with_ids(idx_t n, const float* x, const idx_t* xids) override;
|
|
115
131
|
|
|
@@ -334,6 +334,7 @@ struct IVFPQFastScanScanner : InvertedListScanner {
|
|
|
334
334
|
const IDSelector* sel_in)
|
|
335
335
|
: InvertedListScanner(store_pairs_in, sel_in), index(index_in) {
|
|
336
336
|
this->keep_max = is_similarity_metric(index_in.metric_type);
|
|
337
|
+
this->code_size = index_in.code_size;
|
|
337
338
|
residual.resize(index_in.d);
|
|
338
339
|
}
|
|
339
340
|
|
|
@@ -162,8 +162,7 @@ struct RaBitInvertedListScanner : InvertedListScanner {
|
|
|
162
162
|
std::vector<float> query_vector;
|
|
163
163
|
|
|
164
164
|
std::unique_ptr<FlatCodesDistanceComputer> dc;
|
|
165
|
-
RaBitQDistanceComputer* rabitq_dc =
|
|
166
|
-
nullptr; // For multi-bit adaptive filtering
|
|
165
|
+
RaBitQDistanceComputer* rabitq_dc = nullptr;
|
|
167
166
|
|
|
168
167
|
uint8_t qb = 0;
|
|
169
168
|
bool centered = false;
|
|
@@ -205,30 +204,15 @@ struct RaBitInvertedListScanner : InvertedListScanner {
|
|
|
205
204
|
return dc->distance_to_code(code);
|
|
206
205
|
}
|
|
207
206
|
|
|
208
|
-
// redefiniing the scan_codes allows to inline the distance_to_code
|
|
209
|
-
// (this is unlikely to matter because it contains a virtual function call)
|
|
210
|
-
size_t scan_codes_1bit(
|
|
211
|
-
size_t list_size,
|
|
212
|
-
const uint8_t* codes,
|
|
213
|
-
const idx_t* ids,
|
|
214
|
-
ResultHandler& handler) const {
|
|
215
|
-
return run_scan_codes(*this, list_size, codes, ids, handler);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/// Override scan_codes to implement adaptive filtering for multi-bit codes
|
|
219
207
|
size_t scan_codes(
|
|
220
208
|
size_t list_size,
|
|
221
209
|
const uint8_t* codes,
|
|
222
210
|
const idx_t* ids,
|
|
223
211
|
ResultHandler& handler) const override {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
// For 1-bit codes, use default implementation
|
|
227
|
-
if (ex_bits == 0 || rabitq_dc == nullptr) {
|
|
228
|
-
return scan_codes_1bit(list_size, codes, ids, handler);
|
|
212
|
+
if (qb == 0 && ivf_rabitq.rabitq.nb_bits == 1) {
|
|
213
|
+
return run_scan_codes(*this, list_size, codes, ids, handler);
|
|
229
214
|
}
|
|
230
215
|
|
|
231
|
-
// Multi-bit: Two-stage search with adaptive filtering
|
|
232
216
|
return rabitq_dc->scan_codes_multibit(
|
|
233
217
|
list_size,
|
|
234
218
|
codes,
|
|
@@ -247,7 +231,6 @@ struct RaBitInvertedListScanner : InvertedListScanner {
|
|
|
247
231
|
if (!dc) {
|
|
248
232
|
dc.reset(ivf_rabitq.rabitq.get_distance_computer(
|
|
249
233
|
qb, nullptr, centered));
|
|
250
|
-
// Try to cast to RaBitQDistanceComputer for multi-bit support
|
|
251
234
|
rabitq_dc = dynamic_cast<RaBitQDistanceComputer*>(dc.get());
|
|
252
235
|
FAISS_THROW_IF_NOT(rabitq_dc);
|
|
253
236
|
}
|
|
@@ -19,9 +19,11 @@
|
|
|
19
19
|
#include <faiss/impl/ResultHandler.h>
|
|
20
20
|
#include <faiss/impl/fast_scan/FastScanDistancePostProcessing.h>
|
|
21
21
|
#include <faiss/impl/fast_scan/fast_scan.h>
|
|
22
|
+
#include <faiss/impl/platform_macros.h>
|
|
22
23
|
#include <faiss/impl/simd_dispatch.h>
|
|
23
24
|
#include <faiss/invlists/BlockInvertedLists.h>
|
|
24
25
|
#include <faiss/utils/distances.h>
|
|
26
|
+
#include <faiss/utils/quantize_lut.h>
|
|
25
27
|
#include <faiss/utils/rabitq_simd.h>
|
|
26
28
|
#include <faiss/utils/utils.h>
|
|
27
29
|
|
|
@@ -401,12 +403,14 @@ void IndexIVFRaBitQFastScan::compute_residual_LUT(
|
|
|
401
403
|
uint8_t qb_param,
|
|
402
404
|
bool centered_param,
|
|
403
405
|
std::vector<float>& rotated_q,
|
|
404
|
-
std::vector<float>& centroid_buf
|
|
406
|
+
std::vector<float>& centroid_buf,
|
|
407
|
+
std::vector<uint8_t>& rotated_qq,
|
|
408
|
+
float* rotated_q_out) const {
|
|
405
409
|
const size_t d_val = static_cast<size_t>(d);
|
|
406
410
|
FAISS_THROW_IF_NOT(d_val > 0);
|
|
407
411
|
rotated_q.resize(d_val);
|
|
408
412
|
centroid_buf.resize(d_val);
|
|
409
|
-
|
|
413
|
+
rotated_qq.resize(d_val);
|
|
410
414
|
|
|
411
415
|
// Compute residual
|
|
412
416
|
quantizer->reconstruct(centroid_id, centroid_buf.data());
|
|
@@ -414,7 +418,9 @@ void IndexIVFRaBitQFastScan::compute_residual_LUT(
|
|
|
414
418
|
rotated_q[i] = query[i] - centroid_buf[i];
|
|
415
419
|
}
|
|
416
420
|
|
|
417
|
-
//
|
|
421
|
+
// Keep the caller's rotated_q capacity across the assignment below, so a
|
|
422
|
+
// reused QueryFactorsData does not reallocate on every call.
|
|
423
|
+
std::vector<float> rotated_q_keep = std::move(query_factors.rotated_q);
|
|
418
424
|
query_factors = rabitq_utils::compute_query_factors(
|
|
419
425
|
rotated_q.data(),
|
|
420
426
|
d_val,
|
|
@@ -432,7 +438,12 @@ void IndexIVFRaBitQFastScan::compute_residual_LUT(
|
|
|
432
438
|
}
|
|
433
439
|
|
|
434
440
|
if (rabitq.nb_bits > 1) {
|
|
435
|
-
|
|
441
|
+
if (rotated_q_out != nullptr) {
|
|
442
|
+
std::copy(rotated_q.begin(), rotated_q.end(), rotated_q_out);
|
|
443
|
+
} else {
|
|
444
|
+
rotated_q_keep.assign(rotated_q.begin(), rotated_q.end());
|
|
445
|
+
query_factors.rotated_q = std::move(rotated_q_keep);
|
|
446
|
+
}
|
|
436
447
|
}
|
|
437
448
|
|
|
438
449
|
// Build LUT using branchless subset-sum construction
|
|
@@ -528,8 +539,15 @@ void IndexIVFRaBitQFastScan::search_preassigned(
|
|
|
528
539
|
}
|
|
529
540
|
|
|
530
541
|
std::vector<QueryFactorsData> query_factors_storage(n * cur_nprobe);
|
|
542
|
+
// One block for the multi-bit rotated queries, allocated here rather than
|
|
543
|
+
// per (query, probe) on OpenMP workers: under jemalloc heap profiling on
|
|
544
|
+
// aarch64, worker-thread allocations are very expensive to sample.
|
|
545
|
+
// Left uninitialised; every slot read is written by compute_LUT first.
|
|
546
|
+
std::unique_ptr<float[]> rotated_q_storage(
|
|
547
|
+
rabitq.nb_bits > 1 ? new float[n * cur_nprobe * d] : nullptr);
|
|
531
548
|
FastScanDistancePostProcessing context;
|
|
532
549
|
context.query_factors = query_factors_storage.data();
|
|
550
|
+
context.rotated_q = rotated_q_storage.get();
|
|
533
551
|
context.nprobe = cur_nprobe;
|
|
534
552
|
context.qb = used_qb;
|
|
535
553
|
context.centered = used_centered;
|
|
@@ -570,6 +588,7 @@ void IndexIVFRaBitQFastScan::compute_LUT(
|
|
|
570
588
|
{
|
|
571
589
|
std::vector<float> rotated_q(d);
|
|
572
590
|
std::vector<float> centroid_buf(d);
|
|
591
|
+
std::vector<uint8_t> rotated_qq(d);
|
|
573
592
|
|
|
574
593
|
#pragma omp for
|
|
575
594
|
for (idx_t ij = 0; ij < static_cast<idx_t>(n * cq_nprobe); ij++) {
|
|
@@ -587,7 +606,10 @@ void IndexIVFRaBitQFastScan::compute_LUT(
|
|
|
587
606
|
used_qb,
|
|
588
607
|
used_centered,
|
|
589
608
|
rotated_q,
|
|
590
|
-
centroid_buf
|
|
609
|
+
centroid_buf,
|
|
610
|
+
rotated_qq,
|
|
611
|
+
context.rotated_q ? context.rotated_q + ij * d
|
|
612
|
+
: nullptr);
|
|
591
613
|
|
|
592
614
|
if (context.query_factors != nullptr) {
|
|
593
615
|
context.query_factors[ij] = std::move(query_factors_data);
|
|
@@ -628,10 +650,12 @@ void IndexIVFRaBitQFastScan::compute_LUT_uint8(
|
|
|
628
650
|
AlignedTable<float> lut_float(cur_nprobe * dim12);
|
|
629
651
|
std::vector<float> rotated_q(d);
|
|
630
652
|
std::vector<float> centroid_buf(d);
|
|
653
|
+
std::vector<uint8_t> rotated_qq(d);
|
|
631
654
|
std::vector<float> all_mins(cur_nprobe * M);
|
|
632
655
|
std::vector<float> probe_b(cur_nprobe);
|
|
656
|
+
std::vector<float> probe_span(cur_nprobe);
|
|
633
657
|
|
|
634
|
-
#pragma omp for schedule(
|
|
658
|
+
#pragma omp for schedule(FAISS_OMP_DYNAMIC)
|
|
635
659
|
for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
|
|
636
660
|
const float* xi = x + i * d;
|
|
637
661
|
|
|
@@ -650,10 +674,13 @@ void IndexIVFRaBitQFastScan::compute_LUT_uint8(
|
|
|
650
674
|
used_qb,
|
|
651
675
|
used_centered,
|
|
652
676
|
rotated_q,
|
|
653
|
-
centroid_buf
|
|
677
|
+
centroid_buf,
|
|
678
|
+
rotated_qq,
|
|
679
|
+
context.rotated_q ? context.rotated_q + ij * d
|
|
680
|
+
: nullptr);
|
|
654
681
|
|
|
655
682
|
if (context.query_factors != nullptr) {
|
|
656
|
-
context.query_factors[ij] = qf;
|
|
683
|
+
context.query_factors[ij] = std::move(qf);
|
|
657
684
|
}
|
|
658
685
|
} else {
|
|
659
686
|
memset(lut_float.get() + j * dim12,
|
|
@@ -686,13 +713,18 @@ void IndexIVFRaBitQFastScan::compute_LUT_uint8(
|
|
|
686
713
|
span_j += span;
|
|
687
714
|
}
|
|
688
715
|
probe_b[j2] = b_j;
|
|
689
|
-
|
|
716
|
+
probe_span[j2] = span_j;
|
|
690
717
|
glob_b = std::min(glob_b, b_j);
|
|
691
718
|
}
|
|
692
719
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
720
|
+
for (size_t j2 = 0; j2 < cur_nprobe; j2++) {
|
|
721
|
+
glob_max_dis = std::max(
|
|
722
|
+
glob_max_dis,
|
|
723
|
+
probe_span[j2] + probe_b[j2] - glob_b);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
a = quantize_lut::fastscan_lut_scale(
|
|
727
|
+
glob_max_span, glob_max_dis, M + 1);
|
|
696
728
|
|
|
697
729
|
// Second pass: quantize LUT and compute biasq.
|
|
698
730
|
uint8_t* out_base =
|
|
@@ -872,6 +904,7 @@ struct IVFRaBitQFastScanScanner : InvertedListScanner {
|
|
|
872
904
|
AlignedTable<float> lut_float;
|
|
873
905
|
std::vector<float> rotated_q;
|
|
874
906
|
std::vector<float> centroid_buf;
|
|
907
|
+
std::vector<uint8_t> rotated_qq;
|
|
875
908
|
QueryFactorsData query_factors;
|
|
876
909
|
FastScanDistancePostProcessing context;
|
|
877
910
|
std::vector<int> probe_map;
|
|
@@ -893,6 +926,7 @@ struct IVFRaBitQFastScanScanner : InvertedListScanner {
|
|
|
893
926
|
lut_float(16 * index_in.M),
|
|
894
927
|
rotated_q(index_in.d),
|
|
895
928
|
centroid_buf(index_in.d),
|
|
929
|
+
rotated_qq(index_in.d),
|
|
896
930
|
probe_map({0}),
|
|
897
931
|
mins_buf(index_in.M) {
|
|
898
932
|
this->keep_max = is_similarity_metric(index_in.metric_type);
|
|
@@ -924,7 +958,9 @@ struct IVFRaBitQFastScanScanner : InvertedListScanner {
|
|
|
924
958
|
qb,
|
|
925
959
|
centered,
|
|
926
960
|
rotated_q,
|
|
927
|
-
centroid_buf
|
|
961
|
+
centroid_buf,
|
|
962
|
+
rotated_qq,
|
|
963
|
+
nullptr);
|
|
928
964
|
|
|
929
965
|
// Single-probe quantization (simplified inline, no OMP, no 3D)
|
|
930
966
|
const size_t M = index.M;
|
|
@@ -952,7 +988,7 @@ struct IVFRaBitQFastScanScanner : InvertedListScanner {
|
|
|
952
988
|
b += mn;
|
|
953
989
|
}
|
|
954
990
|
|
|
955
|
-
a =
|
|
991
|
+
a = quantize_lut::fastscan_lut_scale(max_span, max_dis, M);
|
|
956
992
|
for (size_t m = 0; m < M; m++) {
|
|
957
993
|
const float* tab = lut_float.get() + m * ksub;
|
|
958
994
|
rabitq::lut_quantize_16_to_uint8<SL>(
|
|
@@ -131,7 +131,9 @@ struct IndexIVFRaBitQFastScan : IndexIVFFastScan {
|
|
|
131
131
|
uint8_t qb_param,
|
|
132
132
|
bool centered_param,
|
|
133
133
|
std::vector<float>& rotated_q,
|
|
134
|
-
std::vector<float>& centroid_buf
|
|
134
|
+
std::vector<float>& centroid_buf,
|
|
135
|
+
std::vector<uint8_t>& rotated_qq,
|
|
136
|
+
float* rotated_q_out) const;
|
|
135
137
|
|
|
136
138
|
private:
|
|
137
139
|
/// Decode FastScan code to RaBitQ residual vector with explicit
|
|
@@ -399,7 +401,8 @@ float IVFRaBitQHeapHandler<C, SL>::compute_full_multibit_distance(
|
|
|
399
401
|
unpack_buf.data(),
|
|
400
402
|
ex_code,
|
|
401
403
|
ex_fac,
|
|
402
|
-
|
|
404
|
+
context->rotated_q ? context->rotated_q + storage_idx_val * dim
|
|
405
|
+
: query_factors.rotated_q.data(),
|
|
403
406
|
is_similarity ? query_factors.q_dot_c : query_factors.qr_to_c_L2sqr,
|
|
404
407
|
dim,
|
|
405
408
|
ex_bits,
|