faiss 0.6.2 → 0.6.4
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 +8 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +3 -1
- data/vendor/faiss/faiss/Clustering.cpp +9 -1
- data/vendor/faiss/faiss/Clustering.h +8 -0
- data/vendor/faiss/faiss/IVFlib.cpp +14 -3
- data/vendor/faiss/faiss/Index.h +2 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +24 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +16 -145
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +0 -6
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +8 -18
- data/vendor/faiss/faiss/IndexBinaryIVF.h +8 -1
- data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
- data/vendor/faiss/faiss/IndexEDEN.h +57 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +21 -54
- data/vendor/faiss/faiss/IndexFlat.h +2 -2
- data/vendor/faiss/faiss/IndexHNSW.cpp +311 -102
- data/vendor/faiss/faiss/IndexHNSW.h +31 -7
- data/vendor/faiss/faiss/IndexIDMap.cpp +26 -8
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +36 -10
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
- data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +49 -23
- data/vendor/faiss/faiss/IndexIVFPQ.h +11 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +19 -49
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
- data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +9 -2
- data/vendor/faiss/faiss/IndexNSG.cpp +7 -2
- data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
- data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
- data/vendor/faiss/faiss/IndexShards.cpp +5 -5
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +6 -5
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +286 -247
- data/vendor/faiss/faiss/SuperKMeans.h +33 -2
- data/vendor/faiss/faiss/VectorTransform.cpp +71 -2
- data/vendor/faiss/faiss/VectorTransform.h +3 -0
- data/vendor/faiss/faiss/clone_index.cpp +8 -0
- data/vendor/faiss/faiss/factory_tools.cpp +47 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +1 -5
- data/vendor/faiss/faiss/gpu/GpuDistance.h +2 -5
- data/vendor/faiss/faiss/gpu/GpuIndex.h +38 -16
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +71 -1
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +1 -5
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +7 -4
- data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
- data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +528 -267
- data/vendor/faiss/faiss/impl/HNSW.h +46 -7
- data/vendor/faiss/faiss/impl/IDSelector.h +44 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NNDescent.cpp +10 -3
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
- data/vendor/faiss/faiss/impl/Panorama.h +20 -9
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +38 -26
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +45 -37
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +239 -72
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +66 -4
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +4 -13
- data/vendor/faiss/faiss/impl/ResultHandler.h +34 -34
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +287 -84
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +26 -10
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +22 -2
- data/vendor/faiss/faiss/impl/VisitedTable.h +20 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +90 -14
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/expanded_scanners.h +5 -1
- data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +1 -0
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +35 -2
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
- data/vendor/faiss/faiss/impl/index_read.cpp +491 -50
- data/vendor/faiss/faiss/impl/index_write.cpp +86 -30
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
- data/vendor/faiss/faiss/impl/platform_macros.h +3 -1
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
- data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +73 -39
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +4 -4
- data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +887 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +2 -2
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +9 -8
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +90 -24
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +30 -30
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +4 -5
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +101 -34
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +169 -13
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +125 -26
- data/vendor/faiss/faiss/impl/simd_dispatch.h +70 -31
- data/vendor/faiss/faiss/index_factory.cpp +40 -7
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +9 -6
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +29 -8
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +47 -5
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +23 -3
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +4 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +10 -4
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +2 -1
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/distances.cpp +30 -11
- data/vendor/faiss/faiss/utils/distances_dispatch.h +30 -24
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +1 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -3
- data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
- data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
- data/vendor/faiss/faiss/utils/hamming.cpp +16 -10
- data/vendor/faiss/faiss/utils/hamming.h +10 -1
- data/vendor/faiss/faiss/utils/hamming_distance/common.h +14 -3
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +24 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +1 -1
- data/vendor/faiss/faiss/utils/hamming_distance/{hamming_computer-avx512_spr.h → hamming_computer-avx512_vpopcnt.h} +85 -24
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +141 -0
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
- data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +194 -30
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +198 -18
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +330 -40
- data/vendor/faiss/faiss/utils/simd_impl/{rabitq_avx512_spr.cpp → rabitq_avx512_vpopcnt.cpp} +112 -23
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +2 -7
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +6 -1
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +34 -0
- data/vendor/faiss/faiss/utils/simd_levels.cpp +196 -47
- data/vendor/faiss/faiss/utils/simd_levels.h +33 -8
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +21 -5
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +0 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a22f4ad8f3c626f1d6571c4cefcb8292965e52eb3b0b77c354f39ed117570c5
|
|
4
|
+
data.tar.gz: b848af534bebc2ecfdfa5fe7eaa270b530d17d5fe5381aea350451aa03c22d9f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4c5083b9733f589fc30c93f429ed4da74fbb4bbdbe2bde17787506cafb178e2715d114e04ed17bd21a1161a096df66a0c502ae6dc245455c1e221737e80a1f3e
|
|
7
|
+
data.tar.gz: 41eb8ce7434c4408fccf238893468e8c808b1961966a9fc495f960d27ff950d5d6a9cafff18a11e14287f5fedc77f83db9118c47c60e06fdc9f86d9987592c7c
|
data/CHANGELOG.md
CHANGED
data/lib/faiss/version.rb
CHANGED
|
@@ -45,6 +45,8 @@ void AutoTuneCriterion::set_groundtruth(
|
|
|
45
45
|
gt_D.resize(nq * gt_nnn_in);
|
|
46
46
|
memcpy(gt_D.data(), gt_D_in, sizeof(gt_D[0]) * nq * gt_nnn_in);
|
|
47
47
|
}
|
|
48
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
49
|
+
gt_I_in != nullptr, "set_groundtruth: gt_I must be non-null");
|
|
48
50
|
gt_I.resize(nq * gt_nnn_in);
|
|
49
51
|
memcpy(gt_I.data(), gt_I_in, sizeof(gt_I[0]) * nq * gt_nnn_in);
|
|
50
52
|
}
|
|
@@ -148,7 +150,7 @@ bool OperatingPoints::add(
|
|
|
148
150
|
}
|
|
149
151
|
// remove non-optimal points from array
|
|
150
152
|
for (size_t i = a.size() - 1; i > 0; --i) {
|
|
151
|
-
if (a[i].t
|
|
153
|
+
if (a[i].t <= a[i - 1].t) {
|
|
152
154
|
a.erase(a.begin() + (i - 1));
|
|
153
155
|
}
|
|
154
156
|
}
|
|
@@ -367,7 +367,7 @@ void Clustering::train_encoded(
|
|
|
367
367
|
? std::numeric_limits<double>::max()
|
|
368
368
|
: std::abs(prev_obj - obj) / std::abs(prev_obj);
|
|
369
369
|
|
|
370
|
-
if (change
|
|
370
|
+
if (change <= early_stop_threshold) {
|
|
371
371
|
if (verbose) {
|
|
372
372
|
printf("\n Converged at iteration %d: "
|
|
373
373
|
"objective did not change\n",
|
|
@@ -439,6 +439,14 @@ float kmeans_clustering(
|
|
|
439
439
|
size_t k,
|
|
440
440
|
const float* x,
|
|
441
441
|
float* centroids) {
|
|
442
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
443
|
+
d <= static_cast<size_t>(std::numeric_limits<int>::max()),
|
|
444
|
+
"kmeans_clustering: d=%zu exceeds INT_MAX",
|
|
445
|
+
d);
|
|
446
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
447
|
+
k <= static_cast<size_t>(std::numeric_limits<int>::max()),
|
|
448
|
+
"kmeans_clustering: k=%zu exceeds INT_MAX",
|
|
449
|
+
k);
|
|
442
450
|
Clustering clus(static_cast<int>(d), static_cast<int>(k));
|
|
443
451
|
clus.verbose = d * n * k > (size_t(1) << 30);
|
|
444
452
|
// display logs if > 1Gflop per iteration
|
|
@@ -75,6 +75,14 @@ struct ClusteringParameters {
|
|
|
75
75
|
/// so the training process stops only if an error
|
|
76
76
|
/// is unchanged from the previous iteration.
|
|
77
77
|
double early_stop_threshold = 0.0;
|
|
78
|
+
|
|
79
|
+
/// Whether to use the SuperKMeans (super fast k-means) variant instead of
|
|
80
|
+
/// the vanilla Clustering implementation. Only honored by callers that
|
|
81
|
+
/// explicitly support it (e.g. IVF level-1 quantizer training). Cannot be
|
|
82
|
+
/// combined with a user-provided clustering index: SuperKMeans assigns
|
|
83
|
+
/// with its own index, so callers that supply both get an exception rather
|
|
84
|
+
/// than a silent downgrade to vanilla Clustering.
|
|
85
|
+
bool use_super_kmeans = false;
|
|
78
86
|
};
|
|
79
87
|
|
|
80
88
|
struct ClusteringIterationStats {
|
|
@@ -592,8 +592,12 @@ void handle_ivf(
|
|
|
592
592
|
static_cast<faiss::IndexIVF*>(faiss::clone_index(clone));
|
|
593
593
|
if (generate_ids) {
|
|
594
594
|
// Assume the quantizer does not natively support add_with_ids.
|
|
595
|
-
|
|
596
|
-
|
|
595
|
+
// The IDMap wraps the cloned quantizer; own_fields makes it delete
|
|
596
|
+
// that quantizer when sharded_index (which owns the IDMap) is
|
|
597
|
+
// freed.
|
|
598
|
+
auto* id_quantizer = new IndexIDMap2(sharded_index->quantizer);
|
|
599
|
+
id_quantizer->own_fields = true;
|
|
600
|
+
sharded_index->quantizer = id_quantizer;
|
|
597
601
|
sharded_index->quantizer->add_with_ids(
|
|
598
602
|
sharded_centroids[i].size() / index->quantizer->d,
|
|
599
603
|
sharded_centroids[i].data(),
|
|
@@ -615,6 +619,7 @@ void handle_ivf(
|
|
|
615
619
|
faiss::write_index(sharded_index, fname);
|
|
616
620
|
delete sharded_index;
|
|
617
621
|
}
|
|
622
|
+
delete clone;
|
|
618
623
|
}
|
|
619
624
|
|
|
620
625
|
void handle_binary_ivf(
|
|
@@ -650,8 +655,13 @@ void handle_binary_ivf(
|
|
|
650
655
|
faiss::clone_binary_index(clone));
|
|
651
656
|
if (generate_ids) {
|
|
652
657
|
// Assume the quantizer does not natively support add_with_ids.
|
|
653
|
-
|
|
658
|
+
// The IDMap wraps the cloned quantizer; own_fields makes it delete
|
|
659
|
+
// that quantizer when sharded_index (which owns the IDMap) is
|
|
660
|
+
// freed.
|
|
661
|
+
auto* id_quantizer =
|
|
654
662
|
new IndexBinaryIDMap2(sharded_index->quantizer);
|
|
663
|
+
id_quantizer->own_fields = true;
|
|
664
|
+
sharded_index->quantizer = id_quantizer;
|
|
655
665
|
sharded_index->quantizer->add_with_ids(
|
|
656
666
|
sharded_centroids[i].size() / reconstruction_size,
|
|
657
667
|
sharded_centroids[i].data(),
|
|
@@ -673,6 +683,7 @@ void handle_binary_ivf(
|
|
|
673
683
|
faiss::write_index_binary(sharded_index, fname);
|
|
674
684
|
delete sharded_index;
|
|
675
685
|
}
|
|
686
|
+
delete clone;
|
|
676
687
|
}
|
|
677
688
|
|
|
678
689
|
template <typename IndexType>
|
data/vendor/faiss/faiss/Index.h
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
#include <cstdio>
|
|
17
17
|
|
|
18
18
|
#define FAISS_VERSION_MAJOR 1
|
|
19
|
-
#define FAISS_VERSION_MINOR
|
|
20
|
-
#define FAISS_VERSION_PATCH
|
|
19
|
+
#define FAISS_VERSION_MINOR 15
|
|
20
|
+
#define FAISS_VERSION_PATCH 1
|
|
21
21
|
|
|
22
22
|
// Macro to combine the version components into a single string
|
|
23
23
|
#ifndef FAISS_STRINGIFY
|
|
@@ -58,8 +58,8 @@ struct AQDistanceComputerDecompress : FlatCodesDistanceComputer {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
float symmetric_dis(idx_t i, idx_t j) final {
|
|
61
|
-
aq.decode(codes + i *
|
|
62
|
-
aq.decode(codes + j *
|
|
61
|
+
aq.decode(codes + i * code_size, tmp.data(), 1);
|
|
62
|
+
aq.decode(codes + j * code_size, tmp.data() + d, 1);
|
|
63
63
|
return vd(tmp.data(), tmp.data() + d);
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -79,7 +79,8 @@ struct AQDistanceComputerLUT : FlatCodesDistanceComputer {
|
|
|
79
79
|
|
|
80
80
|
explicit AQDistanceComputerLUT(const IndexAdditiveQuantizer& iaq)
|
|
81
81
|
: FlatCodesDistanceComputer(iaq.codes.data(), iaq.code_size),
|
|
82
|
-
LUT(iaq.aq->total_codebook_size
|
|
82
|
+
LUT(iaq.aq->total_codebook_size // Storage for LUT.
|
|
83
|
+
+ size_t(iaq.d) * 2), // tmp storage for symmetric distance.
|
|
83
84
|
aq(*iaq.aq),
|
|
84
85
|
d(iaq.d) {}
|
|
85
86
|
|
|
@@ -96,9 +97,9 @@ struct AQDistanceComputerLUT : FlatCodesDistanceComputer {
|
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
float symmetric_dis(idx_t i, idx_t j) final {
|
|
99
|
-
float* tmp = LUT.data();
|
|
100
|
-
aq.decode(codes + i *
|
|
101
|
-
aq.decode(codes + j *
|
|
100
|
+
float* tmp = LUT.data() + aq.total_codebook_size;
|
|
101
|
+
aq.decode(codes + i * code_size, tmp, 1);
|
|
102
|
+
aq.decode(codes + j * code_size, tmp + d, 1);
|
|
102
103
|
return fvec_L2sqr(tmp, tmp + d, d);
|
|
103
104
|
}
|
|
104
105
|
|
|
@@ -234,8 +235,7 @@ void IndexAdditiveQuantizer::search(
|
|
|
234
235
|
float* distances,
|
|
235
236
|
idx_t* labels,
|
|
236
237
|
const SearchParameters* params) const {
|
|
237
|
-
|
|
238
|
-
!params, "search params not supported for this index");
|
|
238
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
239
239
|
|
|
240
240
|
if (aq->search_type == AdditiveQuantizer::ST_decompress) {
|
|
241
241
|
with_VectorDistance(d, metric_type, metric_arg, [&](auto vd) {
|
|
@@ -458,8 +458,7 @@ void AdditiveCoarseQuantizer::search(
|
|
|
458
458
|
float* distances,
|
|
459
459
|
idx_t* labels,
|
|
460
460
|
const SearchParameters* params) const {
|
|
461
|
-
|
|
462
|
-
!params, "search params not supported for this index");
|
|
461
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
463
462
|
|
|
464
463
|
if (metric_type == METRIC_INNER_PRODUCT) {
|
|
465
464
|
aq->knn_centroids_inner_product(n, x, k, distances, labels);
|
|
@@ -36,7 +36,7 @@ void IndexAdditiveQuantizerFastScan::init(
|
|
|
36
36
|
MetricType metric,
|
|
37
37
|
int bbs_) {
|
|
38
38
|
FAISS_THROW_IF_NOT(aq_init != nullptr);
|
|
39
|
-
|
|
39
|
+
FAISS_THROW_IF_MSG(aq_init->nbits.empty(), "nbits must not be empty");
|
|
40
40
|
FAISS_THROW_IF_NOT(aq_init->nbits[0] == 4);
|
|
41
41
|
if (metric == METRIC_INNER_PRODUCT) {
|
|
42
42
|
FAISS_THROW_IF_NOT_MSG(
|
|
@@ -192,8 +192,7 @@ void IndexAdditiveQuantizerFastScan::search(
|
|
|
192
192
|
float* distances,
|
|
193
193
|
idx_t* labels,
|
|
194
194
|
const SearchParameters* params) const {
|
|
195
|
-
|
|
196
|
-
!params, "search params not supported for this index");
|
|
195
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
197
196
|
FAISS_THROW_IF_NOT(k > 0);
|
|
198
197
|
bool rescale = (rescale_norm && norm_scale > 1 && metric_type == METRIC_L2);
|
|
199
198
|
if (!rescale) {
|
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
#include <faiss/IndexBinaryFromFloat.h>
|
|
11
11
|
|
|
12
|
+
#include <faiss/MetricType.h>
|
|
12
13
|
#include <faiss/impl/FaissAssert.h>
|
|
13
14
|
#include <faiss/utils/utils.h>
|
|
14
15
|
#include <algorithm>
|
|
16
|
+
#include <cmath>
|
|
15
17
|
#include <memory>
|
|
16
18
|
|
|
17
19
|
namespace faiss {
|
|
@@ -55,8 +57,7 @@ void IndexBinaryFromFloat::search(
|
|
|
55
57
|
int32_t* distances,
|
|
56
58
|
idx_t* labels,
|
|
57
59
|
const SearchParameters* params) const {
|
|
58
|
-
|
|
59
|
-
!params, "search params not supported for this index");
|
|
60
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
60
61
|
FAISS_THROW_IF_NOT(k > 0);
|
|
61
62
|
|
|
62
63
|
constexpr idx_t bs = 32768;
|
|
@@ -68,8 +69,27 @@ void IndexBinaryFromFloat::search(
|
|
|
68
69
|
binary_to_real(bn * d, x + b * code_size, xf.get());
|
|
69
70
|
|
|
70
71
|
index->search(bn, xf.get(), k, df.get(), labels + b * k);
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
// binary_to_real maps bits to {-1, +1}, so the float distance relates
|
|
73
|
+
// to the Hamming distance differently for each metric. In all cases the
|
|
74
|
+
// mapping is monotonic, so the result order needs no adjustment.
|
|
75
|
+
switch (index->metric_type) {
|
|
76
|
+
case METRIC_INNER_PRODUCT:
|
|
77
|
+
for (int i = 0; i < bn * k; ++i) {
|
|
78
|
+
distances[b * k + i] =
|
|
79
|
+
int32_t(std::round((d - df[i]) / 2.0));
|
|
80
|
+
}
|
|
81
|
+
break;
|
|
82
|
+
case METRIC_L1:
|
|
83
|
+
for (int i = 0; i < bn * k; ++i) {
|
|
84
|
+
distances[b * k + i] = int32_t(std::round(df[i] / 2.0));
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
case METRIC_L2:
|
|
88
|
+
default:
|
|
89
|
+
for (int i = 0; i < bn * k; ++i) {
|
|
90
|
+
distances[b * k + i] = int32_t(std::round(df[i] / 4.0));
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
73
93
|
}
|
|
74
94
|
}
|
|
75
95
|
}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
#include <faiss/IndexBinaryHNSW.h>
|
|
9
9
|
|
|
10
|
-
#include <omp.h>
|
|
11
10
|
#include <cassert>
|
|
12
11
|
#include <cmath>
|
|
13
12
|
#include <cstdio>
|
|
@@ -24,7 +23,6 @@
|
|
|
24
23
|
#include <faiss/impl/ResultHandler.h>
|
|
25
24
|
#include <faiss/impl/VisitedTable.h>
|
|
26
25
|
#include <faiss/utils/Heap.h>
|
|
27
|
-
#include <faiss/utils/hamming.h>
|
|
28
26
|
#include <faiss/utils/random.h>
|
|
29
27
|
|
|
30
28
|
#include <faiss/impl/simd_dispatch.h>
|
|
@@ -40,140 +38,6 @@
|
|
|
40
38
|
|
|
41
39
|
namespace faiss {
|
|
42
40
|
|
|
43
|
-
/**************************************************************
|
|
44
|
-
* add / search blocks of descriptors
|
|
45
|
-
**************************************************************/
|
|
46
|
-
|
|
47
|
-
namespace {
|
|
48
|
-
|
|
49
|
-
void hnsw_add_vertices(
|
|
50
|
-
IndexBinaryHNSW& index_hnsw,
|
|
51
|
-
size_t n0,
|
|
52
|
-
size_t n,
|
|
53
|
-
const uint8_t* x,
|
|
54
|
-
bool verbose,
|
|
55
|
-
bool preset_levels = false) {
|
|
56
|
-
HNSW& hnsw = index_hnsw.hnsw;
|
|
57
|
-
size_t ntotal = n0 + n;
|
|
58
|
-
double t0 = getmillisecs();
|
|
59
|
-
if (verbose) {
|
|
60
|
-
printf("hnsw_add_vertices: adding %zd elements on top of %zd "
|
|
61
|
-
"(preset_levels=%d)\n",
|
|
62
|
-
n,
|
|
63
|
-
n0,
|
|
64
|
-
int(preset_levels));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
int max_level = hnsw.prepare_level_tab(n, preset_levels);
|
|
68
|
-
|
|
69
|
-
if (verbose) {
|
|
70
|
-
printf(" max_level = %d\n", max_level);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
auto& locks = index_hnsw.locks;
|
|
74
|
-
locks.prepare(ntotal);
|
|
75
|
-
|
|
76
|
-
// add vectors from highest to lowest level
|
|
77
|
-
std::vector<int> hist;
|
|
78
|
-
std::vector<int> order(n);
|
|
79
|
-
|
|
80
|
-
{ // make buckets with vectors of the same level
|
|
81
|
-
|
|
82
|
-
// build histogram
|
|
83
|
-
for (size_t i = 0; i < n; i++) {
|
|
84
|
-
HNSW::storage_idx_t pt_id =
|
|
85
|
-
static_cast<HNSW::storage_idx_t>(i + n0);
|
|
86
|
-
int pt_level = hnsw.levels[pt_id] - 1;
|
|
87
|
-
while (pt_level >= static_cast<int>(hist.size())) {
|
|
88
|
-
hist.push_back(0);
|
|
89
|
-
}
|
|
90
|
-
hist[pt_level]++;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// accumulate
|
|
94
|
-
std::vector<int> offsets(hist.size() + 1, 0);
|
|
95
|
-
for (size_t i = 0; i < hist.size() - 1; i++) {
|
|
96
|
-
offsets[i + 1] = offsets[i] + hist[i];
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// bucket sort
|
|
100
|
-
for (size_t i = 0; i < n; i++) {
|
|
101
|
-
HNSW::storage_idx_t pt_id =
|
|
102
|
-
static_cast<HNSW::storage_idx_t>(i + n0);
|
|
103
|
-
int pt_level = hnsw.levels[pt_id] - 1;
|
|
104
|
-
order[offsets[pt_level]++] = pt_id;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
{ // perform add
|
|
109
|
-
RandomGenerator rng2(789);
|
|
110
|
-
|
|
111
|
-
size_t i1 = static_cast<int>(n);
|
|
112
|
-
|
|
113
|
-
for (int pt_level = static_cast<int>(hist.size()) - 1;
|
|
114
|
-
pt_level >= int(!index_hnsw.init_level0);
|
|
115
|
-
pt_level--) {
|
|
116
|
-
size_t i0 = i1 - hist[pt_level];
|
|
117
|
-
|
|
118
|
-
if (verbose) {
|
|
119
|
-
printf("Adding %zu elements at level %d\n", i1 - i0, pt_level);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// random permutation to get rid of dataset order bias
|
|
123
|
-
for (size_t j = i0; j < i1; j++) {
|
|
124
|
-
std::swap(
|
|
125
|
-
order[j],
|
|
126
|
-
order[j + rng2.rand_int(static_cast<int>(i1 - j))]);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
#pragma omp parallel
|
|
130
|
-
{
|
|
131
|
-
std::unique_ptr<VisitedTable> vt = VisitedTable::create(ntotal);
|
|
132
|
-
|
|
133
|
-
std::unique_ptr<DistanceComputer> dis(
|
|
134
|
-
index_hnsw.get_distance_computer());
|
|
135
|
-
bool do_display = verbose && omp_get_thread_num() == 0;
|
|
136
|
-
size_t prev_display = 0;
|
|
137
|
-
|
|
138
|
-
#pragma omp for schedule(dynamic)
|
|
139
|
-
for (int64_t i = i0; i < i1; i++) {
|
|
140
|
-
HNSW::storage_idx_t pt_id = order[i];
|
|
141
|
-
dis->set_query(
|
|
142
|
-
(float*)(x + (pt_id - n0) * index_hnsw.code_size));
|
|
143
|
-
|
|
144
|
-
hnsw.add_with_locks(
|
|
145
|
-
*dis,
|
|
146
|
-
pt_level,
|
|
147
|
-
pt_id,
|
|
148
|
-
locks,
|
|
149
|
-
*vt,
|
|
150
|
-
index_hnsw.keep_max_size_level0 && (pt_level == 0));
|
|
151
|
-
|
|
152
|
-
if (do_display && i - i0 > prev_display + 10000) {
|
|
153
|
-
prev_display = i - i0;
|
|
154
|
-
printf(" %zu / %zu\r", i - i0, i1 - i0);
|
|
155
|
-
fflush(stdout);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
i1 = i0;
|
|
160
|
-
}
|
|
161
|
-
if (index_hnsw.init_level0) {
|
|
162
|
-
FAISS_ASSERT(i1 == 0);
|
|
163
|
-
} else {
|
|
164
|
-
FAISS_ASSERT((i1 - hist[0]) == 0);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (verbose) {
|
|
168
|
-
printf("Done in %.3f ms\n", getmillisecs() - t0);
|
|
169
|
-
}
|
|
170
|
-
if (!index_hnsw.retain_locks) {
|
|
171
|
-
locks.clear();
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
} // anonymous namespace
|
|
176
|
-
|
|
177
41
|
/**************************************************************
|
|
178
42
|
* IndexBinaryHNSW implementation
|
|
179
43
|
**************************************************************/
|
|
@@ -271,18 +135,25 @@ void IndexBinaryHNSW::add(idx_t n, const uint8_t* x) {
|
|
|
271
135
|
storage->add(n, x);
|
|
272
136
|
ntotal = storage->ntotal;
|
|
273
137
|
|
|
274
|
-
|
|
275
|
-
|
|
138
|
+
bool preset_levels = hnsw.levels.size() == static_cast<size_t>(ntotal);
|
|
139
|
+
|
|
140
|
+
hnsw_add_vertices_deterministic(
|
|
141
|
+
hnsw,
|
|
276
142
|
n0,
|
|
277
143
|
n,
|
|
278
|
-
|
|
144
|
+
d,
|
|
145
|
+
init_level0,
|
|
146
|
+
keep_max_size_level0,
|
|
147
|
+
preset_levels,
|
|
279
148
|
verbose,
|
|
280
|
-
|
|
149
|
+
[this] { return get_distance_computer(); },
|
|
150
|
+
[this, x, n0](DistanceComputer& dc, HNSW::storage_idx_t pt_id) {
|
|
151
|
+
dc.set_query((const float*)(x + (pt_id - n0) * code_size));
|
|
152
|
+
});
|
|
281
153
|
}
|
|
282
154
|
|
|
283
155
|
void IndexBinaryHNSW::reset() {
|
|
284
156
|
hnsw.reset();
|
|
285
|
-
locks.clear();
|
|
286
157
|
storage->reset();
|
|
287
158
|
ntotal = 0;
|
|
288
159
|
}
|
|
@@ -293,8 +164,8 @@ void IndexBinaryHNSW::reconstruct(idx_t key, uint8_t* recons) const {
|
|
|
293
164
|
|
|
294
165
|
DistanceComputer* IndexBinaryHNSW::get_distance_computer() const {
|
|
295
166
|
IndexBinaryFlat* flat_storage = dynamic_cast<IndexBinaryFlat*>(storage);
|
|
296
|
-
|
|
297
|
-
flat_storage
|
|
167
|
+
FAISS_THROW_IF_MSG(
|
|
168
|
+
flat_storage == nullptr,
|
|
298
169
|
"IndexBinaryHNSW requires IndexBinaryFlat storage");
|
|
299
170
|
return with_simd_level([&]<SIMDLevel SL>() {
|
|
300
171
|
return make_binary_hnsw_distance_computer_fixSL<SL>(
|
|
@@ -317,8 +188,8 @@ IndexBinaryHNSWCagra::IndexBinaryHNSWCagra(int d_, int M)
|
|
|
317
188
|
}
|
|
318
189
|
|
|
319
190
|
void IndexBinaryHNSWCagra::add(idx_t n, const uint8_t* x) {
|
|
320
|
-
|
|
321
|
-
|
|
191
|
+
FAISS_THROW_IF_MSG(
|
|
192
|
+
base_level_only,
|
|
322
193
|
"Cannot add vectors when base_level_only is set to True");
|
|
323
194
|
|
|
324
195
|
IndexBinaryHNSW::add(n, x);
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
|
|
12
12
|
#include <faiss/IndexBinaryFlat.h>
|
|
13
13
|
#include <faiss/impl/HNSW.h>
|
|
14
|
-
#include <faiss/impl/hnsw/LockVector.h>
|
|
15
14
|
#include <faiss/utils/utils.h>
|
|
16
15
|
|
|
17
16
|
namespace faiss {
|
|
@@ -41,11 +40,6 @@ struct IndexBinaryHNSW : IndexBinary {
|
|
|
41
40
|
// used when GpuIndexBinaryCagra::copyFrom(IndexBinaryHNSW*) is called.
|
|
42
41
|
bool keep_max_size_level0 = false;
|
|
43
42
|
|
|
44
|
-
// Per-node locks for HNSW graph construction.
|
|
45
|
-
LockVector locks;
|
|
46
|
-
// locks are freed after each call to add() unless this flag is set.
|
|
47
|
-
bool retain_locks = false;
|
|
48
|
-
|
|
49
43
|
explicit IndexBinaryHNSW();
|
|
50
44
|
explicit IndexBinaryHNSW(int d, int M = 32);
|
|
51
45
|
explicit IndexBinaryHNSW(IndexBinary* storage, int M = 32);
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
28
28
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
29
29
|
#include <faiss/impl/binary_hamming/IndexBinaryHash_impl.h>
|
|
30
|
-
#include <faiss/utils/hamming_distance/hamming_computer-generic.h>
|
|
30
|
+
#include <faiss/utils/hamming_distance/hamming_computer-generic.h> // IWYU pragma: keep
|
|
31
31
|
#undef THE_SIMD_LEVEL
|
|
32
32
|
|
|
33
33
|
namespace faiss {
|
|
@@ -83,8 +83,7 @@ void IndexBinaryHash::range_search(
|
|
|
83
83
|
int radius,
|
|
84
84
|
RangeSearchResult* result,
|
|
85
85
|
const SearchParameters* params) const {
|
|
86
|
-
|
|
87
|
-
!params, "search params not supported for this index");
|
|
86
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
88
87
|
size_t nlist = 0, ndis = 0, n0 = 0;
|
|
89
88
|
|
|
90
89
|
#pragma omp parallel if (n > 100) reduction(+ : ndis, n0, nlist)
|
|
@@ -116,8 +115,7 @@ void IndexBinaryHash::search(
|
|
|
116
115
|
int32_t* distances,
|
|
117
116
|
idx_t* labels,
|
|
118
117
|
const SearchParameters* params) const {
|
|
119
|
-
|
|
120
|
-
!params, "search params not supported for this index");
|
|
118
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
121
119
|
FAISS_THROW_IF_NOT(k > 0);
|
|
122
120
|
|
|
123
121
|
using HeapForL2 = CMax<int32_t, idx_t>;
|
|
@@ -216,8 +214,7 @@ void IndexBinaryMultiHash::range_search(
|
|
|
216
214
|
int radius,
|
|
217
215
|
RangeSearchResult* result,
|
|
218
216
|
const SearchParameters* params) const {
|
|
219
|
-
|
|
220
|
-
!params, "search params not supported for this index");
|
|
217
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
221
218
|
size_t nlist = 0, ndis = 0, n0 = 0;
|
|
222
219
|
|
|
223
220
|
#pragma omp parallel if (n > 100) reduction(+ : ndis, n0, nlist)
|
|
@@ -249,8 +246,7 @@ void IndexBinaryMultiHash::search(
|
|
|
249
246
|
int32_t* distances,
|
|
250
247
|
idx_t* labels,
|
|
251
248
|
const SearchParameters* params) const {
|
|
252
|
-
|
|
253
|
-
!params, "search params not supported for this index");
|
|
249
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
254
250
|
FAISS_THROW_IF_NOT(k > 0);
|
|
255
251
|
|
|
256
252
|
using HeapForL2 = CMax<int32_t, idx_t>;
|
|
@@ -192,7 +192,7 @@ void IndexBinaryIVF::reconstruct_n(idx_t i0, idx_t ni, uint8_t* recons) const {
|
|
|
192
192
|
continue;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
uint8_t* reconstructed = recons + (id - i0) *
|
|
195
|
+
uint8_t* reconstructed = recons + (id - i0) * code_size;
|
|
196
196
|
reconstruct_from_offset(list_no, offset, reconstructed);
|
|
197
197
|
}
|
|
198
198
|
}
|
|
@@ -206,8 +206,7 @@ void IndexBinaryIVF::search_and_reconstruct(
|
|
|
206
206
|
idx_t* __restrict labels,
|
|
207
207
|
uint8_t* __restrict recons,
|
|
208
208
|
const SearchParameters* params) const {
|
|
209
|
-
|
|
210
|
-
!params, "search params not supported for this index");
|
|
209
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
211
210
|
const size_t nprobe_2 = std::min(nlist, this->nprobe);
|
|
212
211
|
FAISS_THROW_IF_NOT(k > 0);
|
|
213
212
|
FAISS_THROW_IF_NOT(nprobe_2 > 0);
|
|
@@ -234,10 +233,10 @@ void IndexBinaryIVF::search_and_reconstruct(
|
|
|
234
233
|
for (idx_t j = 0; j < k; ++j) {
|
|
235
234
|
idx_t ij = i * k + j;
|
|
236
235
|
idx_t key = labels[ij];
|
|
237
|
-
uint8_t* reconstructed = recons + ij *
|
|
236
|
+
uint8_t* reconstructed = recons + ij * code_size;
|
|
238
237
|
if (key < 0) {
|
|
239
238
|
// Fill with NaNs
|
|
240
|
-
memset(reconstructed, -1,
|
|
239
|
+
memset(reconstructed, -1, code_size);
|
|
241
240
|
} else {
|
|
242
241
|
int list_no = key >> 32;
|
|
243
242
|
int offset = key & 0xffffffff;
|
|
@@ -349,10 +348,6 @@ void IndexBinaryIVF::replace_invlists(InvertedLists* il, bool own) {
|
|
|
349
348
|
own_invlists = own;
|
|
350
349
|
}
|
|
351
350
|
|
|
352
|
-
// IVFBinaryScannerL2, search_knn_hamming_count, BlockSearch,
|
|
353
|
-
// BlockSearchVariableK, search_knn_hamming_per_invlist are now in
|
|
354
|
-
// impl/binary_hamming/IndexBinaryIVF_impl.h (compiled per-ISA)
|
|
355
|
-
|
|
356
351
|
namespace {
|
|
357
352
|
|
|
358
353
|
void search_knn_hamming_heap(
|
|
@@ -462,13 +457,9 @@ void search_knn_hamming_heap(
|
|
|
462
457
|
|
|
463
458
|
} // anonymous namespace
|
|
464
459
|
|
|
465
|
-
// The remaining template code (search_knn_hamming_count,
|
|
466
|
-
// search_knn_hamming_per_invlist, etc.) has been moved to
|
|
467
|
-
// impl/binary_hamming/IndexBinaryIVF_impl.h
|
|
468
|
-
|
|
469
460
|
BinaryInvertedListScanner* IndexBinaryIVF::get_InvertedListScanner(
|
|
470
461
|
bool store_pairs) const {
|
|
471
|
-
return
|
|
462
|
+
return with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
472
463
|
return make_binary_ivf_scanner_fixSL<SL>(code_size, store_pairs);
|
|
473
464
|
});
|
|
474
465
|
}
|
|
@@ -484,7 +475,7 @@ void IndexBinaryIVF::search_preassigned(
|
|
|
484
475
|
bool store_pairs,
|
|
485
476
|
const IVFSearchParameters* params) const {
|
|
486
477
|
if (per_invlist_search) {
|
|
487
|
-
|
|
478
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
488
479
|
search_knn_hamming_per_invlist_fixSL<SL>(
|
|
489
480
|
code_size,
|
|
490
481
|
this,
|
|
@@ -502,7 +493,7 @@ void IndexBinaryIVF::search_preassigned(
|
|
|
502
493
|
search_knn_hamming_heap(
|
|
503
494
|
this, n, x, k, cidx, cdis, dis, idx, store_pairs, params);
|
|
504
495
|
} else {
|
|
505
|
-
|
|
496
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
506
497
|
search_knn_hamming_count_fixSL<SL>(
|
|
507
498
|
code_size,
|
|
508
499
|
store_pairs,
|
|
@@ -524,8 +515,7 @@ void IndexBinaryIVF::range_search(
|
|
|
524
515
|
int radius,
|
|
525
516
|
RangeSearchResult* __restrict res,
|
|
526
517
|
const SearchParameters* params) const {
|
|
527
|
-
|
|
528
|
-
!params, "search params not supported for this index");
|
|
518
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
529
519
|
const size_t nprobe_2 = std::min(nlist, this->nprobe);
|
|
530
520
|
std::unique_ptr<idx_t[]> idx(new idx_t[n * nprobe_2]);
|
|
531
521
|
std::unique_ptr<int32_t[]> coarse_dis(new int32_t[n * nprobe_2]);
|
|
@@ -232,7 +232,14 @@ struct BinaryInvertedListScanner {
|
|
|
232
232
|
virtual uint32_t distance_to_code(const uint8_t* code) const = 0;
|
|
233
233
|
|
|
234
234
|
/** compute the distances to codes. (distances, labels) should be
|
|
235
|
-
* organized as a
|
|
235
|
+
* organized as a max-heap: the scan accepts a code whose distance is
|
|
236
|
+
* below distances[0] and replaces the top. A min-heap caller reads its
|
|
237
|
+
* neutral value as a huge unsigned bound and gets wrong results.
|
|
238
|
+
|
|
239
|
+
*
|
|
240
|
+
* The heap top is the only bound. To keep the k nearest codes inside a
|
|
241
|
+
* radius, seed every heap slot with that radius instead of the neutral
|
|
242
|
+
* value; an unfilled slot keeps its label of -1.
|
|
236
243
|
*
|
|
237
244
|
* @param n number of codes to scan
|
|
238
245
|
* @param codes codes to scan (n * code_size)
|