faiss 0.1.3 → 0.1.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 +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/ext/faiss/extconf.rb +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +36 -33
- data/vendor/faiss/faiss/AutoTune.h +6 -3
- data/vendor/faiss/faiss/Clustering.cpp +16 -12
- data/vendor/faiss/faiss/Index.cpp +3 -4
- data/vendor/faiss/faiss/Index.h +3 -3
- data/vendor/faiss/faiss/IndexBinary.cpp +3 -4
- data/vendor/faiss/faiss/IndexBinary.h +1 -1
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +2 -12
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +1 -2
- data/vendor/faiss/faiss/IndexFlat.cpp +0 -148
- data/vendor/faiss/faiss/IndexFlat.h +0 -51
- data/vendor/faiss/faiss/IndexHNSW.cpp +4 -5
- data/vendor/faiss/faiss/IndexIVF.cpp +118 -31
- data/vendor/faiss/faiss/IndexIVF.h +22 -15
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFFlat.h +2 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +39 -15
- data/vendor/faiss/faiss/IndexIVFPQ.h +25 -9
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1116 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +166 -0
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +8 -9
- data/vendor/faiss/faiss/IndexIVFPQR.h +2 -1
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +1 -2
- data/vendor/faiss/faiss/IndexPQ.cpp +34 -18
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +536 -0
- data/vendor/faiss/faiss/IndexPQFastScan.h +111 -0
- data/vendor/faiss/faiss/IndexPreTransform.cpp +47 -0
- data/vendor/faiss/faiss/IndexPreTransform.h +2 -0
- data/vendor/faiss/faiss/IndexRefine.cpp +256 -0
- data/vendor/faiss/faiss/IndexRefine.h +73 -0
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +1 -1
- data/vendor/faiss/faiss/gpu/GpuDistance.h +1 -1
- data/vendor/faiss/faiss/gpu/GpuIndex.h +16 -9
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +8 -1
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -11
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +19 -2
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +28 -2
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +24 -14
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +29 -2
- data/vendor/faiss/faiss/gpu/GpuResources.h +4 -0
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +60 -27
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +28 -6
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +547 -0
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +51 -0
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +3 -3
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +3 -2
- data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +274 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +7 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +5 -1
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +231 -0
- data/vendor/faiss/faiss/gpu/test/TestUtils.h +33 -0
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -0
- data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +6 -0
- data/vendor/faiss/faiss/gpu/utils/Timer.cpp +5 -6
- data/vendor/faiss/faiss/gpu/utils/Timer.h +2 -2
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +5 -4
- data/vendor/faiss/faiss/impl/HNSW.cpp +2 -4
- data/vendor/faiss/faiss/impl/PolysemousTraining.h +4 -4
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +22 -12
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +2 -0
- data/vendor/faiss/faiss/impl/ResultHandler.h +452 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -19
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +6 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +64 -96
- data/vendor/faiss/faiss/impl/index_write.cpp +34 -25
- data/vendor/faiss/faiss/impl/io.cpp +33 -2
- data/vendor/faiss/faiss/impl/io.h +7 -2
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -15
- data/vendor/faiss/faiss/impl/platform_macros.h +44 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +272 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +169 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +180 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +354 -0
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +559 -0
- data/vendor/faiss/faiss/index_factory.cpp +112 -7
- data/vendor/faiss/faiss/index_io.h +1 -48
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +151 -0
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +76 -0
- data/vendor/faiss/faiss/{DirectMap.cpp → invlists/DirectMap.cpp} +1 -1
- data/vendor/faiss/faiss/{DirectMap.h → invlists/DirectMap.h} +1 -1
- data/vendor/faiss/faiss/{InvertedLists.cpp → invlists/InvertedLists.cpp} +72 -1
- data/vendor/faiss/faiss/{InvertedLists.h → invlists/InvertedLists.h} +32 -1
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +107 -0
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +63 -0
- data/vendor/faiss/faiss/{OnDiskInvertedLists.cpp → invlists/OnDiskInvertedLists.cpp} +21 -6
- data/vendor/faiss/faiss/{OnDiskInvertedLists.h → invlists/OnDiskInvertedLists.h} +5 -2
- data/vendor/faiss/faiss/python/python_callbacks.h +8 -1
- data/vendor/faiss/faiss/utils/AlignedTable.h +141 -0
- data/vendor/faiss/faiss/utils/Heap.cpp +2 -4
- data/vendor/faiss/faiss/utils/Heap.h +61 -50
- data/vendor/faiss/faiss/utils/distances.cpp +164 -319
- data/vendor/faiss/faiss/utils/distances.h +28 -20
- data/vendor/faiss/faiss/utils/distances_simd.cpp +277 -49
- data/vendor/faiss/faiss/utils/extra_distances.cpp +1 -2
- data/vendor/faiss/faiss/utils/hamming-inl.h +4 -4
- data/vendor/faiss/faiss/utils/hamming.cpp +3 -6
- data/vendor/faiss/faiss/utils/hamming.h +2 -7
- data/vendor/faiss/faiss/utils/ordered_key_value.h +98 -0
- data/vendor/faiss/faiss/utils/partitioning.cpp +1256 -0
- data/vendor/faiss/faiss/utils/partitioning.h +69 -0
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +277 -0
- data/vendor/faiss/faiss/utils/quantize_lut.h +80 -0
- data/vendor/faiss/faiss/utils/simdlib.h +31 -0
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +461 -0
- data/vendor/faiss/faiss/utils/simdlib_emulated.h +589 -0
- metadata +43 -141
- data/vendor/faiss/benchs/bench_6bit_codec.cpp +0 -80
- data/vendor/faiss/c_api/AutoTune_c.cpp +0 -83
- data/vendor/faiss/c_api/AutoTune_c.h +0 -66
- data/vendor/faiss/c_api/Clustering_c.cpp +0 -145
- data/vendor/faiss/c_api/Clustering_c.h +0 -123
- data/vendor/faiss/c_api/IndexFlat_c.cpp +0 -140
- data/vendor/faiss/c_api/IndexFlat_c.h +0 -115
- data/vendor/faiss/c_api/IndexIVFFlat_c.cpp +0 -64
- data/vendor/faiss/c_api/IndexIVFFlat_c.h +0 -58
- data/vendor/faiss/c_api/IndexIVF_c.cpp +0 -99
- data/vendor/faiss/c_api/IndexIVF_c.h +0 -142
- data/vendor/faiss/c_api/IndexLSH_c.cpp +0 -37
- data/vendor/faiss/c_api/IndexLSH_c.h +0 -40
- data/vendor/faiss/c_api/IndexPreTransform_c.cpp +0 -21
- data/vendor/faiss/c_api/IndexPreTransform_c.h +0 -32
- data/vendor/faiss/c_api/IndexShards_c.cpp +0 -38
- data/vendor/faiss/c_api/IndexShards_c.h +0 -39
- data/vendor/faiss/c_api/Index_c.cpp +0 -105
- data/vendor/faiss/c_api/Index_c.h +0 -183
- data/vendor/faiss/c_api/MetaIndexes_c.cpp +0 -49
- data/vendor/faiss/c_api/MetaIndexes_c.h +0 -49
- data/vendor/faiss/c_api/clone_index_c.cpp +0 -23
- data/vendor/faiss/c_api/clone_index_c.h +0 -32
- data/vendor/faiss/c_api/error_c.h +0 -42
- data/vendor/faiss/c_api/error_impl.cpp +0 -27
- data/vendor/faiss/c_api/error_impl.h +0 -16
- data/vendor/faiss/c_api/faiss_c.h +0 -58
- data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +0 -98
- data/vendor/faiss/c_api/gpu/GpuAutoTune_c.h +0 -56
- data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +0 -52
- data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.h +0 -68
- data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +0 -17
- data/vendor/faiss/c_api/gpu/GpuIndex_c.h +0 -30
- data/vendor/faiss/c_api/gpu/GpuIndicesOptions_c.h +0 -38
- data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +0 -86
- data/vendor/faiss/c_api/gpu/GpuResources_c.h +0 -66
- data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +0 -54
- data/vendor/faiss/c_api/gpu/StandardGpuResources_c.h +0 -53
- data/vendor/faiss/c_api/gpu/macros_impl.h +0 -42
- data/vendor/faiss/c_api/impl/AuxIndexStructures_c.cpp +0 -220
- data/vendor/faiss/c_api/impl/AuxIndexStructures_c.h +0 -149
- data/vendor/faiss/c_api/index_factory_c.cpp +0 -26
- data/vendor/faiss/c_api/index_factory_c.h +0 -30
- data/vendor/faiss/c_api/index_io_c.cpp +0 -42
- data/vendor/faiss/c_api/index_io_c.h +0 -50
- data/vendor/faiss/c_api/macros_impl.h +0 -110
- data/vendor/faiss/demos/demo_imi_flat.cpp +0 -154
- data/vendor/faiss/demos/demo_imi_pq.cpp +0 -203
- data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +0 -151
- data/vendor/faiss/demos/demo_sift1M.cpp +0 -252
- data/vendor/faiss/demos/demo_weighted_kmeans.cpp +0 -185
- data/vendor/faiss/misc/test_blas.cpp +0 -87
- data/vendor/faiss/tests/test_binary_flat.cpp +0 -62
- data/vendor/faiss/tests/test_dealloc_invlists.cpp +0 -188
- data/vendor/faiss/tests/test_ivfpq_codec.cpp +0 -70
- data/vendor/faiss/tests/test_ivfpq_indexing.cpp +0 -100
- data/vendor/faiss/tests/test_lowlevel_ivf.cpp +0 -573
- data/vendor/faiss/tests/test_merge.cpp +0 -260
- data/vendor/faiss/tests/test_omp_threads.cpp +0 -14
- data/vendor/faiss/tests/test_ondisk_ivf.cpp +0 -225
- data/vendor/faiss/tests/test_pairs_decoding.cpp +0 -193
- data/vendor/faiss/tests/test_params_override.cpp +0 -236
- data/vendor/faiss/tests/test_pq_encoding.cpp +0 -98
- data/vendor/faiss/tests/test_sliding_ivf.cpp +0 -246
- data/vendor/faiss/tests/test_threaded_index.cpp +0 -253
- data/vendor/faiss/tests/test_transfer_invlists.cpp +0 -159
- data/vendor/faiss/tutorial/cpp/1-Flat.cpp +0 -104
- data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +0 -85
- data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +0 -98
- data/vendor/faiss/tutorial/cpp/4-GPU.cpp +0 -122
- data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +0 -104
@@ -93,57 +93,6 @@ struct IndexFlatL2:IndexFlat {
|
|
93
93
|
};
|
94
94
|
|
95
95
|
|
96
|
-
// same as an IndexFlatL2 but a value is subtracted from each distance
|
97
|
-
struct IndexFlatL2BaseShift: IndexFlatL2 {
|
98
|
-
std::vector<float> shift;
|
99
|
-
|
100
|
-
IndexFlatL2BaseShift (idx_t d, size_t nshift, const float *shift);
|
101
|
-
|
102
|
-
void search(
|
103
|
-
idx_t n,
|
104
|
-
const float* x,
|
105
|
-
idx_t k,
|
106
|
-
float* distances,
|
107
|
-
idx_t* labels) const override;
|
108
|
-
};
|
109
|
-
|
110
|
-
|
111
|
-
/** Index that queries in a base_index (a fast one) and refines the
|
112
|
-
* results with an exact search, hopefully improving the results.
|
113
|
-
*/
|
114
|
-
struct IndexRefineFlat: Index {
|
115
|
-
|
116
|
-
/// storage for full vectors
|
117
|
-
IndexFlat refine_index;
|
118
|
-
|
119
|
-
/// faster index to pre-select the vectors that should be filtered
|
120
|
-
Index *base_index;
|
121
|
-
bool own_fields; ///< should the base index be deallocated?
|
122
|
-
|
123
|
-
/// factor between k requested in search and the k requested from
|
124
|
-
/// the base_index (should be >= 1)
|
125
|
-
float k_factor;
|
126
|
-
|
127
|
-
explicit IndexRefineFlat (Index *base_index);
|
128
|
-
|
129
|
-
IndexRefineFlat ();
|
130
|
-
|
131
|
-
void train(idx_t n, const float* x) override;
|
132
|
-
|
133
|
-
void add(idx_t n, const float* x) override;
|
134
|
-
|
135
|
-
void reset() override;
|
136
|
-
|
137
|
-
void search(
|
138
|
-
idx_t n,
|
139
|
-
const float* x,
|
140
|
-
idx_t k,
|
141
|
-
float* distances,
|
142
|
-
idx_t* labels) const override;
|
143
|
-
|
144
|
-
~IndexRefineFlat() override;
|
145
|
-
};
|
146
|
-
|
147
96
|
|
148
97
|
/// optimized version for 1D "vectors".
|
149
98
|
struct IndexFlat1D:IndexFlatL2 {
|
@@ -277,7 +277,7 @@ IndexHNSW::~IndexHNSW() {
|
|
277
277
|
void IndexHNSW::train(idx_t n, const float* x)
|
278
278
|
{
|
279
279
|
FAISS_THROW_IF_NOT_MSG(storage,
|
280
|
-
"Please use
|
280
|
+
"Please use IndexHNSWFlat (or variants) instead of IndexHNSW directly");
|
281
281
|
// hnsw structure does not require training
|
282
282
|
storage->train (n, x);
|
283
283
|
is_trained = true;
|
@@ -288,7 +288,7 @@ void IndexHNSW::search (idx_t n, const float *x, idx_t k,
|
|
288
288
|
|
289
289
|
{
|
290
290
|
FAISS_THROW_IF_NOT_MSG(storage,
|
291
|
-
"Please use
|
291
|
+
"Please use IndexHNSWFlat (or variants) instead of IndexHNSW directly");
|
292
292
|
size_t n1 = 0, n2 = 0, n3 = 0, ndis = 0, nreorder = 0;
|
293
293
|
|
294
294
|
idx_t check_period = InterruptCallback::get_period_hint (
|
@@ -352,7 +352,7 @@ void IndexHNSW::search (idx_t n, const float *x, idx_t k,
|
|
352
352
|
void IndexHNSW::add(idx_t n, const float *x)
|
353
353
|
{
|
354
354
|
FAISS_THROW_IF_NOT_MSG(storage,
|
355
|
-
"Please use
|
355
|
+
"Please use IndexHNSWFlat (or variants) instead of IndexHNSW directly");
|
356
356
|
FAISS_THROW_IF_NOT(is_trained);
|
357
357
|
int n0 = ntotal;
|
358
358
|
storage->add(n, x);
|
@@ -1003,8 +1003,7 @@ int search_from_candidates_2(const HNSW & hnsw,
|
|
1003
1003
|
if (nres < k) {
|
1004
1004
|
faiss::maxheap_push (++nres, D, I, d, v1);
|
1005
1005
|
} else if (d < D[0]) {
|
1006
|
-
faiss::
|
1007
|
-
faiss::maxheap_push (++nres, D, I, d, v1);
|
1006
|
+
faiss::maxheap_replace_top (nres, D, I, d, v1);
|
1008
1007
|
}
|
1009
1008
|
}
|
1010
1009
|
vt.visited[v1] = vt.visno + 1;
|
@@ -88,12 +88,19 @@ void Level1Quantizer::train_q1 (size_t n, const float *x, bool verbose, MetricTy
|
|
88
88
|
}
|
89
89
|
quantizer->is_trained = true;
|
90
90
|
} else if (quantizer_trains_alone == 2) {
|
91
|
-
if (verbose)
|
91
|
+
if (verbose) {
|
92
92
|
printf (
|
93
93
|
"Training L2 quantizer on %zd vectors in %zdD%s\n",
|
94
94
|
n, d,
|
95
95
|
clustering_index ? "(user provided index)" : "");
|
96
|
-
|
96
|
+
}
|
97
|
+
// also accept spherical centroids because in that case
|
98
|
+
// L2 and IP are equivalent
|
99
|
+
FAISS_THROW_IF_NOT (
|
100
|
+
metric_type == METRIC_L2 ||
|
101
|
+
(metric_type == METRIC_INNER_PRODUCT && cp.spherical)
|
102
|
+
);
|
103
|
+
|
97
104
|
Clustering clus (d, nlist, cp);
|
98
105
|
if (!clustering_index) {
|
99
106
|
IndexFlatL2 assigner (d);
|
@@ -263,23 +270,76 @@ void IndexIVF::set_direct_map_type (DirectMap::Type type)
|
|
263
270
|
direct_map.set_type (type, invlists, ntotal);
|
264
271
|
}
|
265
272
|
|
266
|
-
|
273
|
+
/** It is a sad fact of software that a conceptually simple function like this
|
274
|
+
* becomes very complex when you factor in several ways of parallelizing +
|
275
|
+
* interrupt/error handling + collecting stats + min/max collection. The
|
276
|
+
* codepath that is used 95% of time is the one for parallel_mode = 0 */
|
267
277
|
void IndexIVF::search (idx_t n, const float *x, idx_t k,
|
268
278
|
float *distances, idx_t *labels) const
|
269
279
|
{
|
270
|
-
std::unique_ptr<idx_t[]> idx(new idx_t[n * nprobe]);
|
271
|
-
std::unique_ptr<float[]> coarse_dis(new float[n * nprobe]);
|
272
280
|
|
273
|
-
double t0 = getmillisecs();
|
274
|
-
quantizer->search (n, x, nprobe, coarse_dis.get(), idx.get());
|
275
|
-
indexIVF_stats.quantization_time += getmillisecs() - t0;
|
276
281
|
|
277
|
-
|
278
|
-
|
282
|
+
// search function for a subset of queries
|
283
|
+
auto sub_search_func = [this, k]
|
284
|
+
(idx_t n, const float *x, float *distances, idx_t *labels,
|
285
|
+
IndexIVFStats *ivf_stats) {
|
286
|
+
|
287
|
+
std::unique_ptr<idx_t[]> idx(new idx_t[n * nprobe]);
|
288
|
+
std::unique_ptr<float[]> coarse_dis(new float[n * nprobe]);
|
289
|
+
|
290
|
+
double t0 = getmillisecs();
|
291
|
+
quantizer->search (n, x, nprobe, coarse_dis.get(), idx.get());
|
292
|
+
|
293
|
+
double t1 = getmillisecs();
|
294
|
+
invlists->prefetch_lists (idx.get(), n * nprobe);
|
295
|
+
|
296
|
+
search_preassigned (n, x, k, idx.get(), coarse_dis.get(),
|
297
|
+
distances, labels, false, nullptr, ivf_stats);
|
298
|
+
double t2 = getmillisecs();
|
299
|
+
ivf_stats->quantization_time += t1 - t0;
|
300
|
+
ivf_stats->search_time += t2 - t0;
|
301
|
+
};
|
302
|
+
|
303
|
+
|
304
|
+
if ((parallel_mode & ~PARALLEL_MODE_NO_HEAP_INIT) == 0) {
|
305
|
+
int nt = std::min(omp_get_max_threads(), int(n));
|
306
|
+
std::vector<IndexIVFStats> stats(nt);
|
307
|
+
std::mutex exception_mutex;
|
308
|
+
std::string exception_string;
|
309
|
+
|
310
|
+
#pragma omp parallel for if (nt > 1)
|
311
|
+
for(idx_t slice = 0; slice < nt; slice++) {
|
312
|
+
IndexIVFStats local_stats;
|
313
|
+
idx_t i0 = n * slice / nt;
|
314
|
+
idx_t i1 = n * (slice + 1) / nt;
|
315
|
+
if (i1 > i0) {
|
316
|
+
try {
|
317
|
+
sub_search_func(
|
318
|
+
i1 - i0, x + i0 * d,
|
319
|
+
distances + i0 * k, labels + i0 * k,
|
320
|
+
&stats[slice]
|
321
|
+
);
|
322
|
+
} catch(const std::exception & e) {
|
323
|
+
std::lock_guard<std::mutex> lock(exception_mutex);
|
324
|
+
exception_string = e.what();
|
325
|
+
}
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
if (!exception_string.empty()) {
|
330
|
+
FAISS_THROW_MSG (exception_string.c_str());
|
331
|
+
}
|
332
|
+
|
333
|
+
// collect stats
|
334
|
+
for(idx_t slice = 0; slice < nt; slice++) {
|
335
|
+
indexIVF_stats.add(stats[slice]);
|
336
|
+
}
|
337
|
+
} else {
|
338
|
+
// handle paralellization at level below (or don't run in parallel at all)
|
339
|
+
sub_search_func(n, x, distances, labels, &indexIVF_stats);
|
340
|
+
}
|
341
|
+
|
279
342
|
|
280
|
-
search_preassigned (n, x, k, idx.get(), coarse_dis.get(),
|
281
|
-
distances, labels, false);
|
282
|
-
indexIVF_stats.search_time += getmillisecs() - t0;
|
283
343
|
}
|
284
344
|
|
285
345
|
|
@@ -288,7 +348,8 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
|
|
288
348
|
const float *coarse_dis ,
|
289
349
|
float *distances, idx_t *labels,
|
290
350
|
bool store_pairs,
|
291
|
-
const IVFSearchParameters *params
|
351
|
+
const IVFSearchParameters *params,
|
352
|
+
IndexIVFStats *ivf_stats) const
|
292
353
|
{
|
293
354
|
long nprobe = params ? params->nprobe : this->nprobe;
|
294
355
|
long max_codes = params ? params->max_codes : this->max_codes;
|
@@ -305,13 +366,12 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
|
|
305
366
|
int pmode = this->parallel_mode & ~PARALLEL_MODE_NO_HEAP_INIT;
|
306
367
|
bool do_heap_init = !(this->parallel_mode & PARALLEL_MODE_NO_HEAP_INIT);
|
307
368
|
|
308
|
-
// don't start parallel section if single query
|
309
369
|
bool do_parallel = omp_get_max_threads() >= 2 && (
|
310
|
-
pmode == 0 ?
|
370
|
+
pmode == 0 ? false :
|
371
|
+
pmode == 3 ? n > 1 :
|
311
372
|
pmode == 1 ? nprobe > 1 :
|
312
373
|
nprobe * n > 1);
|
313
374
|
|
314
|
-
|
315
375
|
#pragma omp parallel if(do_parallel) reduction(+: nlistv, ndis, nheap)
|
316
376
|
{
|
317
377
|
InvertedListScanner *scanner = get_InvertedListScanner(store_pairs);
|
@@ -409,7 +469,7 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
|
|
409
469
|
* Actual loops, depending on parallel_mode
|
410
470
|
****************************************************/
|
411
471
|
|
412
|
-
if (pmode == 0) {
|
472
|
+
if (pmode == 0 || pmode == 3) {
|
413
473
|
|
414
474
|
#pragma omp for
|
415
475
|
for (idx_t i = 0; i < n; i++) {
|
@@ -527,11 +587,12 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
|
|
527
587
|
}
|
528
588
|
}
|
529
589
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
590
|
+
if (ivf_stats) {
|
591
|
+
ivf_stats->nq += n;
|
592
|
+
ivf_stats->nlist += nlistv;
|
593
|
+
ivf_stats->ndis += ndis;
|
594
|
+
ivf_stats->nheap_updates += nheap;
|
595
|
+
}
|
535
596
|
}
|
536
597
|
|
537
598
|
|
@@ -551,7 +612,7 @@ void IndexIVF::range_search (idx_t nx, const float *x, float radius,
|
|
551
612
|
invlists->prefetch_lists (keys.get(), nx * nprobe);
|
552
613
|
|
553
614
|
range_search_preassigned (nx, x, radius, keys.get (), coarse_dis.get (),
|
554
|
-
result);
|
615
|
+
result, false, nullptr, &indexIVF_stats);
|
555
616
|
|
556
617
|
indexIVF_stats.search_time += getmillisecs() - t0;
|
557
618
|
}
|
@@ -561,7 +622,8 @@ void IndexIVF::range_search_preassigned (
|
|
561
622
|
const idx_t *keys, const float *coarse_dis,
|
562
623
|
RangeSearchResult *result,
|
563
624
|
bool store_pairs,
|
564
|
-
const IVFSearchParameters *params
|
625
|
+
const IVFSearchParameters *params,
|
626
|
+
IndexIVFStats *stats) const
|
565
627
|
{
|
566
628
|
long nprobe = params ? params->nprobe : this->nprobe;
|
567
629
|
long max_codes = params ? params->max_codes : this->max_codes;
|
@@ -574,7 +636,15 @@ void IndexIVF::range_search_preassigned (
|
|
574
636
|
|
575
637
|
std::vector<RangeSearchPartialResult *> all_pres (omp_get_max_threads());
|
576
638
|
|
577
|
-
|
639
|
+
int pmode = this->parallel_mode & ~PARALLEL_MODE_NO_HEAP_INIT;
|
640
|
+
// don't start parallel section if single query
|
641
|
+
bool do_parallel = omp_get_max_threads() >= 2 && (
|
642
|
+
pmode == 3 ? false :
|
643
|
+
pmode == 0 ? nx > 1 :
|
644
|
+
pmode == 1 ? nprobe > 1 :
|
645
|
+
nprobe * nx > 1);
|
646
|
+
|
647
|
+
#pragma omp parallel if(do_parallel) reduction(+: nlistv, ndis)
|
578
648
|
{
|
579
649
|
RangeSearchPartialResult pres(result);
|
580
650
|
std::unique_ptr<InvertedListScanner> scanner
|
@@ -680,9 +750,11 @@ void IndexIVF::range_search_preassigned (
|
|
680
750
|
}
|
681
751
|
}
|
682
752
|
|
683
|
-
|
684
|
-
|
685
|
-
|
753
|
+
if (stats) {
|
754
|
+
stats->nq += nx;
|
755
|
+
stats->nlist += nlistv;
|
756
|
+
stats->ndis += ndis;
|
757
|
+
}
|
686
758
|
}
|
687
759
|
|
688
760
|
|
@@ -879,11 +951,15 @@ void IndexIVF::replace_invlists (InvertedLists *il, bool own)
|
|
879
951
|
{
|
880
952
|
if (own_invlists) {
|
881
953
|
delete invlists;
|
954
|
+
invlists = nullptr;
|
882
955
|
}
|
883
956
|
// FAISS_THROW_IF_NOT (ntotal == 0);
|
884
957
|
if (il) {
|
885
|
-
FAISS_THROW_IF_NOT (il->nlist == nlist
|
886
|
-
|
958
|
+
FAISS_THROW_IF_NOT (il->nlist == nlist);
|
959
|
+
FAISS_THROW_IF_NOT (
|
960
|
+
il->code_size == code_size ||
|
961
|
+
il->code_size == InvertedLists::INVALID_CODE_SIZE
|
962
|
+
);
|
887
963
|
}
|
888
964
|
invlists = il;
|
889
965
|
own_invlists = own;
|
@@ -971,6 +1047,17 @@ void IndexIVFStats::reset()
|
|
971
1047
|
memset ((void*)this, 0, sizeof (*this));
|
972
1048
|
}
|
973
1049
|
|
1050
|
+
void IndexIVFStats::add (const IndexIVFStats & other)
|
1051
|
+
{
|
1052
|
+
nq += other.nq;
|
1053
|
+
nlist += other.nlist;
|
1054
|
+
ndis += other.ndis;
|
1055
|
+
nheap_updates += other.nheap_updates;
|
1056
|
+
quantization_time += other.quantization_time;
|
1057
|
+
search_time += other.search_time;
|
1058
|
+
|
1059
|
+
}
|
1060
|
+
|
974
1061
|
|
975
1062
|
IndexIVFStats indexIVF_stats;
|
976
1063
|
|
@@ -16,8 +16,8 @@
|
|
16
16
|
#include <stdint.h>
|
17
17
|
|
18
18
|
#include <faiss/Index.h>
|
19
|
-
#include <faiss/InvertedLists.h>
|
20
|
-
#include <faiss/DirectMap.h>
|
19
|
+
#include <faiss/invlists/InvertedLists.h>
|
20
|
+
#include <faiss/invlists/DirectMap.h>
|
21
21
|
#include <faiss/Clustering.h>
|
22
22
|
#include <faiss/impl/platform_macros.h>
|
23
23
|
#include <faiss/utils/Heap.h>
|
@@ -76,6 +76,7 @@ struct IVFSearchParameters {
|
|
76
76
|
|
77
77
|
|
78
78
|
struct InvertedListScanner;
|
79
|
+
struct IndexIVFStats;
|
79
80
|
|
80
81
|
/** Index based on a inverted file (IVF)
|
81
82
|
*
|
@@ -109,9 +110,10 @@ struct IndexIVF: Index, Level1Quantizer {
|
|
109
110
|
|
110
111
|
/** Parallel mode determines how queries are parallelized with OpenMP
|
111
112
|
*
|
112
|
-
* 0 (default):
|
113
|
+
* 0 (default): split over queries
|
113
114
|
* 1: parallelize over inverted lists
|
114
115
|
* 2: parallelize over both
|
116
|
+
* 3: split over queries with a finer granularity
|
115
117
|
*
|
116
118
|
* PARALLEL_MODE_NO_HEAP_INIT: binary or with the previous to
|
117
119
|
* prevent the heap to be initialized and finalized
|
@@ -178,14 +180,16 @@ struct IndexIVF: Index, Level1Quantizer {
|
|
178
180
|
* instead in upper/lower 32 bit of result,
|
179
181
|
* instead of ids (used for reranking).
|
180
182
|
* @param params used to override the object's search parameters
|
183
|
+
* @param stats search stats to be updated (can be null)
|
181
184
|
*/
|
182
|
-
virtual void search_preassigned (
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
185
|
+
virtual void search_preassigned (
|
186
|
+
idx_t n, const float *x, idx_t k,
|
187
|
+
const idx_t *assign, const float *centroid_dis,
|
188
|
+
float *distances, idx_t *labels,
|
189
|
+
bool store_pairs,
|
190
|
+
const IVFSearchParameters *params=nullptr,
|
191
|
+
IndexIVFStats *stats=nullptr
|
192
|
+
) const;
|
189
193
|
|
190
194
|
/** assign the vectors, then call search_preassign */
|
191
195
|
void search (idx_t n, const float *x, idx_t k,
|
@@ -194,11 +198,13 @@ struct IndexIVF: Index, Level1Quantizer {
|
|
194
198
|
void range_search (idx_t n, const float* x, float radius,
|
195
199
|
RangeSearchResult* result) const override;
|
196
200
|
|
197
|
-
void range_search_preassigned(
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
201
|
+
void range_search_preassigned(
|
202
|
+
idx_t nx, const float *x, float radius,
|
203
|
+
const idx_t *keys, const float *coarse_dis,
|
204
|
+
RangeSearchResult *result,
|
205
|
+
bool store_pairs=false,
|
206
|
+
const IVFSearchParameters *params=nullptr,
|
207
|
+
IndexIVFStats *stats=nullptr) const;
|
202
208
|
|
203
209
|
/// get a scanner for this index (store_pairs means ignore labels)
|
204
210
|
virtual InvertedListScanner *get_InvertedListScanner (
|
@@ -364,6 +370,7 @@ struct IndexIVFStats {
|
|
364
370
|
|
365
371
|
IndexIVFStats () {reset (); }
|
366
372
|
void reset ();
|
373
|
+
void add (const IndexIVFStats & other);
|
367
374
|
};
|
368
375
|
|
369
376
|
// global var that collects them all
|
@@ -159,9 +159,8 @@ struct IVFFlatScanner: InvertedListScanner {
|
|
159
159
|
float dis = metric == METRIC_INNER_PRODUCT ?
|
160
160
|
fvec_inner_product (xi, yj, d) : fvec_L2sqr (xi, yj, d);
|
161
161
|
if (C::cmp (simi[0], dis)) {
|
162
|
-
heap_pop<C> (k, simi, idxi);
|
163
162
|
int64_t id = store_pairs ? lo_build (list_no, j) : ids[j];
|
164
|
-
|
163
|
+
heap_replace_top<C> (k, simi, idxi, dis, id);
|
165
164
|
nup++;
|
166
165
|
}
|
167
166
|
}
|
@@ -317,7 +316,8 @@ void IndexIVFFlatDedup::search_preassigned (
|
|
317
316
|
const float *centroid_dis,
|
318
317
|
float *distances, idx_t *labels,
|
319
318
|
bool store_pairs,
|
320
|
-
const IVFSearchParameters *params
|
319
|
+
const IVFSearchParameters *params,
|
320
|
+
IndexIVFStats *stats) const
|
321
321
|
{
|
322
322
|
FAISS_THROW_IF_NOT_MSG (
|
323
323
|
!store_pairs, "store_pairs not supported in IVFDedup");
|
@@ -77,7 +77,8 @@ struct IndexIVFFlatDedup: IndexIVFFlat {
|
|
77
77
|
const float *centroid_dis,
|
78
78
|
float *distances, idx_t *labels,
|
79
79
|
bool store_pairs,
|
80
|
-
const IVFSearchParameters *params=nullptr
|
80
|
+
const IVFSearchParameters *params=nullptr,
|
81
|
+
IndexIVFStats *stats=nullptr
|
81
82
|
) const override;
|
82
83
|
|
83
84
|
size_t remove_ids(const IDSelector& sel) override;
|