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
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
#include <faiss/IndexScalarQuantizer.h>
|
|
19
19
|
#include <faiss/impl/HNSW.h>
|
|
20
20
|
#include <faiss/impl/Panorama.h>
|
|
21
|
-
#include <faiss/impl/hnsw/LockVector.h>
|
|
22
21
|
#include <faiss/utils/utils.h>
|
|
23
22
|
|
|
24
23
|
namespace faiss {
|
|
@@ -53,11 +52,6 @@ struct IndexHNSW : Index {
|
|
|
53
52
|
// See impl/VisitedTable.h.
|
|
54
53
|
std::optional<bool> use_visited_hashset;
|
|
55
54
|
|
|
56
|
-
// Per-node locks for HNSW graph construction.
|
|
57
|
-
LockVector locks;
|
|
58
|
-
// locks are freed after each call to add() unless this flag is set.
|
|
59
|
-
bool retain_locks = false;
|
|
60
|
-
|
|
61
55
|
explicit IndexHNSW(int d = 0, int M = 32, MetricType metric = METRIC_L2);
|
|
62
56
|
explicit IndexHNSW(Index* storage, int M = 32);
|
|
63
57
|
|
|
@@ -216,6 +210,36 @@ struct IndexHNSWSQ : IndexHNSW {
|
|
|
216
210
|
MetricType metric = METRIC_L2);
|
|
217
211
|
};
|
|
218
212
|
|
|
213
|
+
/** HNSW index whose storage is RaBitQ-compressed.
|
|
214
|
+
*
|
|
215
|
+
* The graph is built directly from the compressed codes. Neighbor-diversity
|
|
216
|
+
* pruning uses a fast 1-bit symmetric L2 estimator, including when the storage
|
|
217
|
+
* contains multi-bit codes.
|
|
218
|
+
*
|
|
219
|
+
* With nb_bits >= 2 the codes carry a per-vector error factor, so search uses
|
|
220
|
+
* the staged search method: a 1-bit estimate for every neighbor and the full
|
|
221
|
+
* multi-bit distance only for candidates the error bound cannot rule out.
|
|
222
|
+
* nb_bits = 1 has no error factor and uses ordinary HNSW search.
|
|
223
|
+
*/
|
|
224
|
+
struct IndexHNSWRaBitQ : IndexHNSW {
|
|
225
|
+
IndexHNSWRaBitQ();
|
|
226
|
+
IndexHNSWRaBitQ(
|
|
227
|
+
int d,
|
|
228
|
+
int M,
|
|
229
|
+
uint8_t nb_bits = 1,
|
|
230
|
+
MetricType metric = METRIC_L2);
|
|
231
|
+
|
|
232
|
+
IndexHNSWRaBitQ& operator=(const IndexHNSWRaBitQ&) = delete;
|
|
233
|
+
|
|
234
|
+
private:
|
|
235
|
+
// clone_index() replaces the shallow-copied storage with a deep copy
|
|
236
|
+
// before returning it. Keep ordinary C++ copies from sharing ownership.
|
|
237
|
+
IndexHNSWRaBitQ(const IndexHNSWRaBitQ&) = default;
|
|
238
|
+
#ifndef SWIG
|
|
239
|
+
friend IndexHNSW* clone_IndexHNSW(const IndexHNSW* index);
|
|
240
|
+
#endif
|
|
241
|
+
};
|
|
242
|
+
|
|
219
243
|
/** 2-level code structure with fast random access
|
|
220
244
|
*/
|
|
221
245
|
struct IndexHNSW2Level : IndexHNSW {
|
|
@@ -253,7 +277,7 @@ struct IndexHNSWCagra : IndexHNSW {
|
|
|
253
277
|
/// searches only the base level knn graph of the HNSW index.
|
|
254
278
|
/// This parameter selects the entry point by randomly selecting
|
|
255
279
|
/// some points and using the best one.
|
|
256
|
-
int num_base_level_search_entrypoints =
|
|
280
|
+
int num_base_level_search_entrypoints = 256;
|
|
257
281
|
|
|
258
282
|
void add(idx_t n, const float* x) override;
|
|
259
283
|
|
|
@@ -138,7 +138,8 @@ void IndexIDMapTemplate<IndexT>::add_sa_codes(
|
|
|
138
138
|
idx_t n,
|
|
139
139
|
const uint8_t* codes,
|
|
140
140
|
const idx_t* xids) {
|
|
141
|
-
index
|
|
141
|
+
// don't pass the ids to the sub-index, they are kept in id_map
|
|
142
|
+
index->add_sa_codes(n, codes, nullptr);
|
|
142
143
|
for (idx_t i = 0; i < n; i++) {
|
|
143
144
|
id_map.push_back(xids[i]);
|
|
144
145
|
}
|
|
@@ -228,15 +229,20 @@ void IndexIDMapTemplate<IndexT>::range_search(
|
|
|
228
229
|
typename IndexT::distance_t radius,
|
|
229
230
|
RangeSearchResult* result,
|
|
230
231
|
const SearchParameters* params) const {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
IDSelectorTranslated id_selector_translated(id_map, params->sel);
|
|
234
|
-
internal_search_parameters.sel = &id_selector_translated;
|
|
232
|
+
IDSelectorTranslated this_idtrans(this->id_map, nullptr);
|
|
233
|
+
ScopedSelChange sel_change;
|
|
235
234
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
235
|
+
if (params && params->sel) {
|
|
236
|
+
auto idtrans = dynamic_cast<const IDSelectorTranslated*>(params->sel);
|
|
237
|
+
|
|
238
|
+
if (!idtrans) {
|
|
239
|
+
// Preserve the concrete params type and its index-specific fields.
|
|
240
|
+
auto params_non_const = const_cast<SearchParameters*>(params);
|
|
241
|
+
this_idtrans.sel = params->sel;
|
|
242
|
+
sel_change.set(params_non_const, &this_idtrans);
|
|
243
|
+
}
|
|
239
244
|
}
|
|
245
|
+
index->range_search(n, x, radius, result, params);
|
|
240
246
|
|
|
241
247
|
const idx_t id_map_size = static_cast<idx_t>(id_map.size());
|
|
242
248
|
#pragma omp parallel for
|
|
@@ -329,6 +335,18 @@ void IndexIDMap2Template<IndexT>::add_with_ids(
|
|
|
329
335
|
xids);
|
|
330
336
|
}
|
|
331
337
|
|
|
338
|
+
template <typename IndexT>
|
|
339
|
+
void IndexIDMap2Template<IndexT>::add_sa_codes(
|
|
340
|
+
idx_t n,
|
|
341
|
+
const uint8_t* codes,
|
|
342
|
+
const idx_t* xids) {
|
|
343
|
+
idx_t prev_ntotal = this->ntotal;
|
|
344
|
+
IndexIDMapTemplate<IndexT>::add_sa_codes(n, codes, xids);
|
|
345
|
+
for (idx_t i = prev_ntotal; i < this->ntotal; i++) {
|
|
346
|
+
rev_map[this->id_map[i]] = i;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
332
350
|
template <typename IndexT>
|
|
333
351
|
void IndexIDMap2Template<IndexT>::check_consistency() const {
|
|
334
352
|
FAISS_THROW_IF_NOT(rev_map.size() == this->id_map.size());
|
|
@@ -110,6 +110,8 @@ struct IndexIDMap2Template : IndexIDMapTemplate<IndexT> {
|
|
|
110
110
|
NumericType numeric_type,
|
|
111
111
|
const idx_t* xids) override;
|
|
112
112
|
|
|
113
|
+
void add_sa_codes(idx_t n, const uint8_t* x, const idx_t* xids) override;
|
|
114
|
+
|
|
113
115
|
size_t remove_ids(const IDSelector& sel) override;
|
|
114
116
|
|
|
115
117
|
void reconstruct(idx_t key, component_t* recons) const override;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
#include <faiss/IndexIVF.h>
|
|
9
|
+
#include <faiss/SuperKMeans.h>
|
|
9
10
|
|
|
10
11
|
#include <omp.h>
|
|
11
12
|
#include <atomic>
|
|
@@ -17,7 +18,6 @@
|
|
|
17
18
|
#include <cstdio>
|
|
18
19
|
#include <limits>
|
|
19
20
|
|
|
20
|
-
#include <faiss/utils/hamming.h>
|
|
21
21
|
#include <faiss/utils/utils.h>
|
|
22
22
|
|
|
23
23
|
#include <faiss/IndexFlat.h>
|
|
@@ -79,13 +79,27 @@ void Level1Quantizer::train_q1(
|
|
|
79
79
|
printf("Training level-1 quantizer on %zd vectors in %zdD\n", n, d);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
FAISS_THROW_IF_MSG(
|
|
83
|
+
cp.use_super_kmeans && clustering_index,
|
|
84
|
+
"cp.use_super_kmeans is incompatible with a user-provided "
|
|
85
|
+
"clustering_index: SuperKMeans assigns with its own index");
|
|
86
|
+
|
|
83
87
|
quantizer->reset();
|
|
84
|
-
if (
|
|
85
|
-
|
|
88
|
+
if (cp.use_super_kmeans) {
|
|
89
|
+
SuperKMeansParameters super_cp;
|
|
90
|
+
static_cast<ClusteringParameters&>(super_cp) = cp;
|
|
91
|
+
SuperKMeans clus(
|
|
92
|
+
static_cast<int>(d), static_cast<int>(nlist), super_cp);
|
|
93
|
+
clus.train(n, x);
|
|
86
94
|
quantizer->add(nlist, clus.centroids.data());
|
|
87
95
|
} else {
|
|
88
|
-
clus
|
|
96
|
+
Clustering clus(static_cast<int>(d), static_cast<int>(nlist), cp);
|
|
97
|
+
if (clustering_index) {
|
|
98
|
+
clus.train(n, x, *clustering_index);
|
|
99
|
+
quantizer->add(nlist, clus.centroids.data());
|
|
100
|
+
} else {
|
|
101
|
+
clus.train(n, x, *quantizer);
|
|
102
|
+
}
|
|
89
103
|
}
|
|
90
104
|
quantizer->is_trained = true;
|
|
91
105
|
} else if (quantizer_trains_alone == 2) {
|
|
@@ -501,7 +515,7 @@ void IndexIVF::search_preassigned(
|
|
|
501
515
|
if (!do_heap_init) {
|
|
502
516
|
return;
|
|
503
517
|
}
|
|
504
|
-
if (metric_type
|
|
518
|
+
if (is_similarity_metric(metric_type)) {
|
|
505
519
|
heap_heapify<HeapForIP>(k, simi, idxi);
|
|
506
520
|
} else {
|
|
507
521
|
heap_heapify<HeapForL2>(k, simi, idxi);
|
|
@@ -512,7 +526,7 @@ void IndexIVF::search_preassigned(
|
|
|
512
526
|
const idx_t* local_idx,
|
|
513
527
|
float* simi,
|
|
514
528
|
idx_t* idxi) {
|
|
515
|
-
if (metric_type
|
|
529
|
+
if (is_similarity_metric(metric_type)) {
|
|
516
530
|
heap_addn<HeapForIP>(
|
|
517
531
|
k, simi, idxi, local_dis, local_idx, k);
|
|
518
532
|
} else {
|
|
@@ -525,7 +539,7 @@ void IndexIVF::search_preassigned(
|
|
|
525
539
|
if (!do_heap_init) {
|
|
526
540
|
return;
|
|
527
541
|
}
|
|
528
|
-
if (metric_type
|
|
542
|
+
if (is_similarity_metric(metric_type)) {
|
|
529
543
|
heap_reorder<HeapForIP>(k, simi, idxi);
|
|
530
544
|
} else {
|
|
531
545
|
heap_reorder<HeapForL2>(k, simi, idxi);
|
|
@@ -599,7 +613,7 @@ void IndexIVF::search_preassigned(
|
|
|
599
613
|
|
|
600
614
|
size_t old_scan_cnt = 0;
|
|
601
615
|
size_t old_heap_updates = 0;
|
|
602
|
-
if (metric_type
|
|
616
|
+
if (is_similarity_metric(metric_type)) {
|
|
603
617
|
HeapResultHandler<HeapForIP, false> handler(
|
|
604
618
|
k, simi, idxi);
|
|
605
619
|
old_scan_cnt = handler.stats.scan_cnt;
|
|
@@ -1056,7 +1070,19 @@ InvertedListScanner* IndexIVF::get_InvertedListScanner(
|
|
|
1056
1070
|
|
|
1057
1071
|
void IndexIVF::reconstruct(idx_t key, float* recons) const {
|
|
1058
1072
|
idx_t lo = direct_map.get(key);
|
|
1059
|
-
|
|
1073
|
+
const size_t list_no = lo_listno(lo);
|
|
1074
|
+
const size_t offset = lo_offset(lo);
|
|
1075
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1076
|
+
list_no < nlist,
|
|
1077
|
+
"IndexIVF::reconstruct: list_no %zd out of range (nlist=%zd)",
|
|
1078
|
+
list_no,
|
|
1079
|
+
nlist);
|
|
1080
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1081
|
+
offset < invlists->list_size(list_no),
|
|
1082
|
+
"IndexIVF::reconstruct: offset %zd out of range (list_size=%zd)",
|
|
1083
|
+
offset,
|
|
1084
|
+
invlists->list_size(list_no));
|
|
1085
|
+
reconstruct_from_offset(list_no, offset, recons);
|
|
1060
1086
|
}
|
|
1061
1087
|
|
|
1062
1088
|
void IndexIVF::reconstruct_n(idx_t i0, idx_t ni, float* recons) const {
|
|
@@ -283,7 +283,7 @@ InvertedListScanner* IndexIVFAdditiveQuantizer::get_InvertedListScanner(
|
|
|
283
283
|
bool store_pairs,
|
|
284
284
|
const IDSelector* sel,
|
|
285
285
|
const IVFSearchParameters*) const {
|
|
286
|
-
|
|
286
|
+
FAISS_THROW_IF_MSG(sel, "id selector not supported for this index");
|
|
287
287
|
if (metric_type == METRIC_INNER_PRODUCT) {
|
|
288
288
|
if (aq->search_type == AdditiveQuantizer::ST_decompress) {
|
|
289
289
|
return new AQInvertedListScannerDecompress<true>(
|
|
@@ -48,8 +48,8 @@ void IndexIVFAdditiveQuantizerFastScan::init(
|
|
|
48
48
|
MetricType metric,
|
|
49
49
|
int bbs_,
|
|
50
50
|
bool own_invlists_) {
|
|
51
|
-
FAISS_THROW_IF_NOT(aq_
|
|
52
|
-
|
|
51
|
+
FAISS_THROW_IF_NOT(aq_);
|
|
52
|
+
FAISS_THROW_IF_MSG(aq_->nbits.empty(), "quantizer nbits must not be empty");
|
|
53
53
|
FAISS_THROW_IF_NOT(aq_->nbits[0] == 4);
|
|
54
54
|
if (metric == METRIC_INNER_PRODUCT) {
|
|
55
55
|
FAISS_THROW_IF_NOT_MSG(
|
|
@@ -310,8 +310,7 @@ void IndexIVFAdditiveQuantizerFastScan::search(
|
|
|
310
310
|
float* distances,
|
|
311
311
|
idx_t* labels,
|
|
312
312
|
const SearchParameters* params) const {
|
|
313
|
-
|
|
314
|
-
!params, "search params not supported for this index");
|
|
313
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
315
314
|
|
|
316
315
|
FAISS_THROW_IF_NOT(k > 0);
|
|
317
316
|
bool rescale = (rescale_norm && norm_scale > 1 && metric_type == METRIC_L2);
|
|
@@ -0,0 +1,302 @@
|
|
|
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
|
+
#include <faiss/IndexIVFEDEN.h>
|
|
9
|
+
|
|
10
|
+
#include <omp.h>
|
|
11
|
+
|
|
12
|
+
#include <cstddef>
|
|
13
|
+
#include <cstdint>
|
|
14
|
+
#include <cstring>
|
|
15
|
+
#include <memory>
|
|
16
|
+
#include <vector>
|
|
17
|
+
|
|
18
|
+
#include <faiss/impl/EDENQuantizer.h>
|
|
19
|
+
#include <faiss/impl/FaissAssert.h>
|
|
20
|
+
#include <faiss/impl/expanded_scanners.h>
|
|
21
|
+
|
|
22
|
+
namespace faiss {
|
|
23
|
+
|
|
24
|
+
IndexIVFEDEN::IndexIVFEDEN(
|
|
25
|
+
Index* quantizer_in,
|
|
26
|
+
const size_t d_in,
|
|
27
|
+
const size_t nlist_in,
|
|
28
|
+
MetricType metric,
|
|
29
|
+
bool own_invlists_in,
|
|
30
|
+
uint8_t nb_bits_in,
|
|
31
|
+
EDENScaleType scale_type_in)
|
|
32
|
+
: IndexIVF(quantizer_in, d_in, nlist_in, 0, metric, own_invlists_in),
|
|
33
|
+
sq(d_in, eden_utils::quantizer_type_for_bits(nb_bits_in)),
|
|
34
|
+
scale_type(scale_type_in) {
|
|
35
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
36
|
+
scale_type == EDENScaleType_UNBIASED ||
|
|
37
|
+
scale_type == EDENScaleType_BIASED,
|
|
38
|
+
"invalid EDEN scale type");
|
|
39
|
+
sq.train(0, nullptr);
|
|
40
|
+
code_size = eden_utils::code_size(d, sq.bits);
|
|
41
|
+
if (own_invlists_in) {
|
|
42
|
+
invlists->code_size = code_size;
|
|
43
|
+
}
|
|
44
|
+
is_trained = false;
|
|
45
|
+
by_residual = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
IndexIVFEDEN::IndexIVFEDEN() {
|
|
49
|
+
by_residual = true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void IndexIVFEDEN::train_encoder(
|
|
53
|
+
idx_t n,
|
|
54
|
+
const float* x,
|
|
55
|
+
const idx_t* /*assign*/) {
|
|
56
|
+
sq.train(n, x);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
void IndexIVFEDEN::encode_vectors(
|
|
60
|
+
idx_t n,
|
|
61
|
+
const float* x,
|
|
62
|
+
const idx_t* list_nos,
|
|
63
|
+
uint8_t* codes,
|
|
64
|
+
bool include_listnos) const {
|
|
65
|
+
const size_t coarse_size = include_listnos ? coarse_code_size() : 0;
|
|
66
|
+
memset(codes, 0, (code_size + coarse_size) * n);
|
|
67
|
+
|
|
68
|
+
#pragma omp parallel if (n > 1000)
|
|
69
|
+
{
|
|
70
|
+
std::vector<float> centroid(d);
|
|
71
|
+
|
|
72
|
+
#pragma omp for
|
|
73
|
+
for (idx_t i = 0; i < n; i++) {
|
|
74
|
+
const int64_t list_no = list_nos[i];
|
|
75
|
+
if (list_no >= 0) {
|
|
76
|
+
const float* xi = x + i * d;
|
|
77
|
+
uint8_t* code = codes + i * (code_size + coarse_size);
|
|
78
|
+
|
|
79
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
80
|
+
eden_utils::compute_codes(
|
|
81
|
+
sq,
|
|
82
|
+
metric_type,
|
|
83
|
+
scale_type,
|
|
84
|
+
xi,
|
|
85
|
+
code + coarse_size,
|
|
86
|
+
1,
|
|
87
|
+
centroid.data());
|
|
88
|
+
|
|
89
|
+
if (coarse_size) {
|
|
90
|
+
encode_listno(list_no, code);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
void IndexIVFEDEN::decode_vectors(
|
|
98
|
+
idx_t n,
|
|
99
|
+
const uint8_t* codes,
|
|
100
|
+
const idx_t* listnos,
|
|
101
|
+
float* x) const {
|
|
102
|
+
#pragma omp parallel
|
|
103
|
+
{
|
|
104
|
+
std::vector<float> centroid(d);
|
|
105
|
+
|
|
106
|
+
#pragma omp for
|
|
107
|
+
for (idx_t i = 0; i < n; i++) {
|
|
108
|
+
const uint8_t* code = codes + i * code_size;
|
|
109
|
+
const int64_t list_no = listnos[i];
|
|
110
|
+
float* xi = x + i * d;
|
|
111
|
+
|
|
112
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
113
|
+
eden_utils::decode(sq, code, xi, 1, centroid.data());
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void IndexIVFEDEN::add_core(
|
|
119
|
+
idx_t n,
|
|
120
|
+
const float* x,
|
|
121
|
+
const idx_t* xids,
|
|
122
|
+
const idx_t* precomputed_idx,
|
|
123
|
+
void* inverted_list_context) {
|
|
124
|
+
FAISS_THROW_IF_NOT(is_trained);
|
|
125
|
+
|
|
126
|
+
DirectMapAdd dm_add(direct_map, n, xids);
|
|
127
|
+
|
|
128
|
+
#pragma omp parallel
|
|
129
|
+
{
|
|
130
|
+
std::vector<uint8_t> one_code(code_size);
|
|
131
|
+
std::vector<float> centroid(d);
|
|
132
|
+
|
|
133
|
+
const int nt = omp_get_num_threads();
|
|
134
|
+
const int rank = omp_get_thread_num();
|
|
135
|
+
|
|
136
|
+
for (idx_t i = 0; i < n; i++) {
|
|
137
|
+
const int64_t list_no = precomputed_idx[i];
|
|
138
|
+
if (list_no >= 0 && list_no % nt == rank) {
|
|
139
|
+
const int64_t id = xids ? xids[i] : ntotal + i;
|
|
140
|
+
const float* xi = x + i * d;
|
|
141
|
+
|
|
142
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
143
|
+
eden_utils::compute_codes(
|
|
144
|
+
sq,
|
|
145
|
+
metric_type,
|
|
146
|
+
scale_type,
|
|
147
|
+
xi,
|
|
148
|
+
one_code.data(),
|
|
149
|
+
1,
|
|
150
|
+
centroid.data());
|
|
151
|
+
|
|
152
|
+
const size_t ofs = invlists->add_entry(
|
|
153
|
+
list_no, id, one_code.data(), inverted_list_context);
|
|
154
|
+
dm_add.add(i, list_no, ofs);
|
|
155
|
+
} else if (rank == 0 && list_no == -1) {
|
|
156
|
+
dm_add.add(i, -1, 0);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
ntotal += n;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
namespace {
|
|
165
|
+
|
|
166
|
+
struct EDENInvertedListScanner : InvertedListScanner {
|
|
167
|
+
using InvertedListScanner::scan_codes;
|
|
168
|
+
|
|
169
|
+
const IndexIVFEDEN& ivf_eden;
|
|
170
|
+
std::vector<float> reconstructed_centroid;
|
|
171
|
+
std::vector<float> query_vector;
|
|
172
|
+
std::unique_ptr<FlatCodesDistanceComputer> dc;
|
|
173
|
+
|
|
174
|
+
explicit EDENInvertedListScanner(
|
|
175
|
+
const IndexIVFEDEN& ivf_eden_in,
|
|
176
|
+
bool store_pairs_in = false,
|
|
177
|
+
const IDSelector* sel_in = nullptr)
|
|
178
|
+
: InvertedListScanner(store_pairs_in, sel_in),
|
|
179
|
+
ivf_eden(ivf_eden_in) {
|
|
180
|
+
keep_max = is_similarity_metric(ivf_eden.metric_type);
|
|
181
|
+
code_size = ivf_eden.code_size;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
void set_query(const float* query_vector_in) override {
|
|
185
|
+
query_vector.assign(query_vector_in, query_vector_in + ivf_eden.d);
|
|
186
|
+
internal_try_setup_dc();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
void set_list(idx_t list_no_in, float /*coarse_dis*/) override {
|
|
190
|
+
list_no = list_no_in;
|
|
191
|
+
|
|
192
|
+
reconstructed_centroid.resize(ivf_eden.d);
|
|
193
|
+
ivf_eden.quantizer->reconstruct(
|
|
194
|
+
list_no_in, reconstructed_centroid.data());
|
|
195
|
+
internal_try_setup_dc();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
float distance_to_code(const uint8_t* code) const final {
|
|
199
|
+
return dc->distance_to_code(code);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
size_t scan_codes(
|
|
203
|
+
size_t list_size,
|
|
204
|
+
const uint8_t* codes,
|
|
205
|
+
const idx_t* ids,
|
|
206
|
+
ResultHandler& handler) const override {
|
|
207
|
+
return run_scan_codes(*this, list_size, codes, ids, handler);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
void internal_try_setup_dc() {
|
|
211
|
+
if (!query_vector.empty() && !reconstructed_centroid.empty()) {
|
|
212
|
+
dc.reset(
|
|
213
|
+
eden_utils::get_distance_computer(
|
|
214
|
+
ivf_eden.sq,
|
|
215
|
+
ivf_eden.metric_type,
|
|
216
|
+
reconstructed_centroid.data()));
|
|
217
|
+
dc->set_query(query_vector.data());
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
} // namespace
|
|
223
|
+
|
|
224
|
+
InvertedListScanner* IndexIVFEDEN::get_InvertedListScanner(
|
|
225
|
+
bool store_pairs,
|
|
226
|
+
const IDSelector* sel,
|
|
227
|
+
const IVFSearchParameters* /*params*/) const {
|
|
228
|
+
return new EDENInvertedListScanner(*this, store_pairs, sel);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void IndexIVFEDEN::reconstruct_from_offset(
|
|
232
|
+
int64_t list_no,
|
|
233
|
+
int64_t offset,
|
|
234
|
+
float* recons) const {
|
|
235
|
+
const uint8_t* code = invlists->get_single_code(list_no, offset);
|
|
236
|
+
|
|
237
|
+
std::vector<float> centroid(d);
|
|
238
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
239
|
+
eden_utils::decode(sq, code, recons, 1, centroid.data());
|
|
240
|
+
|
|
241
|
+
invlists->release_codes(list_no, code);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
void IndexIVFEDEN::sa_decode(idx_t n, const uint8_t* bytes, float* x) const {
|
|
245
|
+
const size_t coarse_size = coarse_code_size();
|
|
246
|
+
|
|
247
|
+
#pragma omp parallel
|
|
248
|
+
{
|
|
249
|
+
std::vector<float> centroid(d);
|
|
250
|
+
|
|
251
|
+
#pragma omp for
|
|
252
|
+
for (idx_t i = 0; i < n; i++) {
|
|
253
|
+
const uint8_t* code = bytes + i * (code_size + coarse_size);
|
|
254
|
+
const int64_t list_no = decode_listno(code);
|
|
255
|
+
float* xi = x + i * d;
|
|
256
|
+
|
|
257
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
258
|
+
eden_utils::decode(sq, code + coarse_size, xi, 1, centroid.data());
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
struct IVFEDENDistanceComputer : DistanceComputer {
|
|
264
|
+
const float* q = nullptr;
|
|
265
|
+
const IndexIVFEDEN* parent = nullptr;
|
|
266
|
+
|
|
267
|
+
void set_query(const float* x) override {
|
|
268
|
+
q = x;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
float operator()(idx_t i) override {
|
|
272
|
+
const idx_t lo = parent->direct_map.get(i);
|
|
273
|
+
const uint64_t list_no = lo_listno(lo);
|
|
274
|
+
const uint64_t offset = lo_offset(lo);
|
|
275
|
+
const uint8_t* code =
|
|
276
|
+
parent->invlists->get_single_code(list_no, offset);
|
|
277
|
+
|
|
278
|
+
std::vector<float> centroid(parent->d);
|
|
279
|
+
parent->quantizer->reconstruct(list_no, centroid.data());
|
|
280
|
+
|
|
281
|
+
std::unique_ptr<FlatCodesDistanceComputer> dc(
|
|
282
|
+
eden_utils::get_distance_computer(
|
|
283
|
+
parent->sq, parent->metric_type, centroid.data()));
|
|
284
|
+
dc->set_query(q);
|
|
285
|
+
const float distance = dc->distance_to_code(code);
|
|
286
|
+
|
|
287
|
+
parent->invlists->release_codes(list_no, code);
|
|
288
|
+
return distance;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
float symmetric_dis(idx_t /*i*/, idx_t /*j*/) override {
|
|
292
|
+
FAISS_THROW_MSG("Not implemented");
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
DistanceComputer* IndexIVFEDEN::get_distance_computer() const {
|
|
297
|
+
IVFEDENDistanceComputer* dc = new IVFEDENDistanceComputer;
|
|
298
|
+
dc->parent = this;
|
|
299
|
+
return dc;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
} // namespace faiss
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <cstddef>
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
|
|
13
|
+
#include <faiss/IndexIVF.h>
|
|
14
|
+
#include <faiss/impl/EDENQuantizer.h>
|
|
15
|
+
|
|
16
|
+
namespace faiss {
|
|
17
|
+
|
|
18
|
+
struct IndexIVFEDEN : IndexIVF {
|
|
19
|
+
ScalarQuantizer sq;
|
|
20
|
+
EDENScaleType scale_type = EDENScaleType_UNBIASED;
|
|
21
|
+
|
|
22
|
+
// Factory strings: IVF<nlist>,EDEN, IVF<nlist>,EDEN<n>, and the same
|
|
23
|
+
// forms with the BIASED suffix for EDEN's MSE-minimizing scale.
|
|
24
|
+
IndexIVFEDEN(
|
|
25
|
+
Index* quantizer,
|
|
26
|
+
const size_t d,
|
|
27
|
+
const size_t nlist,
|
|
28
|
+
MetricType metric = METRIC_L2,
|
|
29
|
+
bool own_invlists = true,
|
|
30
|
+
uint8_t nb_bits = 1,
|
|
31
|
+
EDENScaleType scale_type = EDENScaleType_UNBIASED);
|
|
32
|
+
|
|
33
|
+
IndexIVFEDEN();
|
|
34
|
+
|
|
35
|
+
void train_encoder(idx_t n, const float* x, const idx_t* assign) override;
|
|
36
|
+
|
|
37
|
+
void encode_vectors(
|
|
38
|
+
idx_t n,
|
|
39
|
+
const float* x,
|
|
40
|
+
const idx_t* list_nos,
|
|
41
|
+
uint8_t* codes,
|
|
42
|
+
bool include_listnos = false) const override;
|
|
43
|
+
|
|
44
|
+
void decode_vectors(
|
|
45
|
+
idx_t n,
|
|
46
|
+
const uint8_t* codes,
|
|
47
|
+
const idx_t* list_nos,
|
|
48
|
+
float* x) const override;
|
|
49
|
+
|
|
50
|
+
void add_core(
|
|
51
|
+
idx_t n,
|
|
52
|
+
const float* x,
|
|
53
|
+
const idx_t* xids,
|
|
54
|
+
const idx_t* precomputed_idx,
|
|
55
|
+
void* inverted_list_context = nullptr) override;
|
|
56
|
+
|
|
57
|
+
InvertedListScanner* get_InvertedListScanner(
|
|
58
|
+
bool store_pairs,
|
|
59
|
+
const IDSelector* sel,
|
|
60
|
+
const IVFSearchParameters* params) const override;
|
|
61
|
+
|
|
62
|
+
void reconstruct_from_offset(int64_t list_no, int64_t offset, float* recons)
|
|
63
|
+
const override;
|
|
64
|
+
|
|
65
|
+
void sa_decode(idx_t n, const uint8_t* bytes, float* x) const override;
|
|
66
|
+
|
|
67
|
+
DistanceComputer* get_distance_computer() const override;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
} // namespace faiss
|
|
@@ -376,9 +376,8 @@ void IndexIVFFastScan::search_preassigned(
|
|
|
376
376
|
cur_nprobe = params->nprobe;
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
FAISS_THROW_IF_NOT_MSG(!stats, "stats not supported for this index");
|
|
379
|
+
FAISS_THROW_IF_MSG(store_pairs, "store_pairs not supported for this index");
|
|
380
|
+
FAISS_THROW_IF_MSG(stats, "stats not supported for this index");
|
|
382
381
|
FAISS_THROW_IF_NOT(k > 0);
|
|
383
382
|
FastScanDistancePostProcessing empty_context{};
|
|
384
383
|
|
|
@@ -404,8 +403,8 @@ void IndexIVFFastScan::range_search(
|
|
|
404
403
|
params->max_lists_num == 0,
|
|
405
404
|
"max_lists_num is a knn knob and is not honored by "
|
|
406
405
|
"fastscan range search");
|
|
407
|
-
|
|
408
|
-
|
|
406
|
+
FAISS_THROW_IF_MSG(
|
|
407
|
+
params->ensure_topk_full,
|
|
409
408
|
"ensure_topk_full is a knn knob and is not honored by "
|
|
410
409
|
"fastscan range search");
|
|
411
410
|
FAISS_THROW_IF_NOT_MSG(
|
|
@@ -1592,7 +1591,7 @@ void IndexIVFFastScan::reconstruct_from_offset(
|
|
|
1592
1591
|
}
|
|
1593
1592
|
|
|
1594
1593
|
void IndexIVFFastScan::reconstruct_orig_invlists() {
|
|
1595
|
-
FAISS_THROW_IF_NOT(orig_invlists
|
|
1594
|
+
FAISS_THROW_IF_NOT(orig_invlists);
|
|
1596
1595
|
FAISS_THROW_IF_NOT(orig_invlists->list_size(0) == 0);
|
|
1597
1596
|
|
|
1598
1597
|
#pragma omp parallel for if (nlist > 100)
|