faiss 0.5.2 → 0.6.0
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 +16 -0
- data/LICENSE.txt +1 -1
- data/ext/faiss/ext.cpp +1 -1
- data/ext/faiss/extconf.rb +5 -6
- data/ext/faiss/index_binary.cpp +76 -17
- data/ext/faiss/{index.cpp → index_rb.cpp} +108 -35
- data/ext/faiss/kmeans.cpp +12 -9
- data/ext/faiss/numo.hpp +11 -9
- data/ext/faiss/pca_matrix.cpp +10 -8
- data/ext/faiss/product_quantizer.cpp +14 -12
- data/ext/faiss/{utils.cpp → utils_rb.cpp} +10 -3
- data/ext/faiss/{utils.h → utils_rb.h} +6 -0
- data/lib/faiss/version.rb +1 -1
- data/lib/faiss.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +130 -11
- data/vendor/faiss/faiss/AutoTune.h +14 -1
- data/vendor/faiss/faiss/Clustering.cpp +59 -10
- data/vendor/faiss/faiss/Clustering.h +12 -0
- data/vendor/faiss/faiss/IVFlib.cpp +31 -28
- data/vendor/faiss/faiss/Index.cpp +20 -8
- data/vendor/faiss/faiss/Index.h +25 -3
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +19 -24
- data/vendor/faiss/faiss/IndexBinary.cpp +1 -0
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +9 -4
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +45 -11
- data/vendor/faiss/faiss/IndexFastScan.cpp +35 -22
- data/vendor/faiss/faiss/IndexFastScan.h +10 -1
- data/vendor/faiss/faiss/IndexFlat.cpp +193 -136
- data/vendor/faiss/faiss/IndexFlat.h +16 -1
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +46 -22
- data/vendor/faiss/faiss/IndexFlatCodes.h +7 -1
- data/vendor/faiss/faiss/IndexHNSW.cpp +24 -50
- data/vendor/faiss/faiss/IndexHNSW.h +14 -12
- data/vendor/faiss/faiss/IndexIDMap.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVF.cpp +76 -49
- data/vendor/faiss/faiss/IndexIVF.h +14 -4
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +11 -8
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +2 -2
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +25 -14
- data/vendor/faiss/faiss/IndexIVFFastScan.h +26 -22
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +10 -61
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +39 -111
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +89 -147
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +37 -5
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +42 -30
- data/vendor/faiss/faiss/IndexIVFRaBitQ.h +2 -2
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +246 -97
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +32 -29
- data/vendor/faiss/faiss/IndexLSH.cpp +8 -6
- data/vendor/faiss/faiss/IndexLattice.cpp +29 -24
- data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -0
- data/vendor/faiss/faiss/IndexNSG.cpp +2 -1
- data/vendor/faiss/faiss/IndexNSG.h +0 -2
- data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +1 -1
- data/vendor/faiss/faiss/IndexPQ.cpp +19 -10
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +26 -13
- data/vendor/faiss/faiss/IndexRaBitQ.h +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +132 -78
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +14 -12
- data/vendor/faiss/faiss/IndexRefine.cpp +0 -30
- data/vendor/faiss/faiss/IndexShards.cpp +3 -4
- data/vendor/faiss/faiss/MetricType.h +16 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +120 -0
- data/vendor/faiss/faiss/VectorTransform.h +23 -0
- data/vendor/faiss/faiss/clone_index.cpp +7 -4
- data/vendor/faiss/faiss/{cppcontrib/factory_tools.cpp → factory_tools.cpp} +1 -1
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +1 -1
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +37 -11
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +0 -28
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +367 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.h +107 -0
- data/vendor/faiss/faiss/impl/CodePacker.cpp +4 -0
- data/vendor/faiss/faiss/impl/CodePacker.h +11 -3
- data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +83 -0
- data/vendor/faiss/faiss/impl/CodePackerRaBitQ.h +47 -0
- data/vendor/faiss/faiss/impl/FaissAssert.h +60 -2
- data/vendor/faiss/faiss/impl/HNSW.cpp +25 -34
- data/vendor/faiss/faiss/impl/HNSW.h +8 -6
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +34 -27
- data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -1
- data/vendor/faiss/faiss/impl/NSG.cpp +6 -5
- data/vendor/faiss/faiss/impl/NSG.h +17 -7
- data/vendor/faiss/faiss/impl/Panorama.cpp +53 -46
- data/vendor/faiss/faiss/impl/Panorama.h +22 -6
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +16 -5
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +70 -58
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +92 -0
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +93 -31
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +12 -28
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +3 -10
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +15 -41
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +0 -4
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +14 -9
- data/vendor/faiss/faiss/impl/ResultHandler.h +131 -50
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +67 -2358
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +0 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +42 -0
- data/vendor/faiss/faiss/impl/VisitedTable.h +69 -0
- data/vendor/faiss/faiss/impl/expanded_scanners.h +158 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +829 -471
- data/vendor/faiss/faiss/impl/index_read_utils.h +0 -1
- data/vendor/faiss/faiss/impl/index_write.cpp +17 -8
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +47 -20
- data/vendor/faiss/faiss/impl/mapped_io.cpp +9 -2
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +7 -2
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +11 -3
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +19 -13
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +29 -21
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx2.h → pq_code_distance/pq_code_distance-avx2.cpp} +42 -215
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx512.h → pq_code_distance/pq_code_distance-avx512.cpp} +68 -107
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +141 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +23 -0
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-sve.h → pq_code_distance/pq_code_distance-sve.cpp} +57 -144
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +9 -6
- data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +121 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +136 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +280 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +164 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +94 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +455 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +430 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +329 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +467 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +203 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +42 -0
- data/vendor/faiss/faiss/impl/simd_dispatch.h +139 -0
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +18 -18
- data/vendor/faiss/faiss/index_factory.cpp +35 -16
- data/vendor/faiss/faiss/index_io.h +29 -3
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +7 -4
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +9 -19
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +2 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +2 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +9 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +9 -0
- data/vendor/faiss/faiss/utils/Heap.cpp +46 -0
- data/vendor/faiss/faiss/utils/Heap.h +21 -0
- data/vendor/faiss/faiss/utils/NeuralNet.cpp +10 -7
- data/vendor/faiss/faiss/utils/distances.cpp +141 -23
- data/vendor/faiss/faiss/utils/distances.h +98 -0
- data/vendor/faiss/faiss/utils/distances_dispatch.h +170 -0
- data/vendor/faiss/faiss/utils/distances_simd.cpp +74 -3511
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +164 -157
- data/vendor/faiss/faiss/utils/extra_distances.cpp +52 -95
- data/vendor/faiss/faiss/utils/extra_distances.h +47 -1
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -1
- data/vendor/faiss/faiss/utils/partitioning.cpp +1 -1
- data/vendor/faiss/faiss/utils/pq_code_distance.h +251 -0
- data/vendor/faiss/faiss/utils/rabitq_simd.h +260 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +150 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +568 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +153 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +1185 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +1092 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_sse-inl.h +391 -0
- data/vendor/faiss/faiss/utils/simd_levels.cpp +322 -0
- data/vendor/faiss/faiss/utils/simd_levels.h +91 -0
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +12 -1
- data/vendor/faiss/faiss/utils/simdlib_avx512.h +69 -0
- data/vendor/faiss/faiss/utils/simdlib_neon.h +6 -0
- data/vendor/faiss/faiss/utils/sorting.cpp +4 -4
- data/vendor/faiss/faiss/utils/utils.cpp +16 -9
- metadata +47 -18
- data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +0 -81
- data/vendor/faiss/faiss/impl/code_distance/code_distance.h +0 -186
- /data/vendor/faiss/faiss/{cppcontrib/factory_tools.h → factory_tools.h} +0 -0
|
@@ -12,14 +12,19 @@
|
|
|
12
12
|
|
|
13
13
|
#include <cstdio>
|
|
14
14
|
#include <cstdlib>
|
|
15
|
+
#include <cstring>
|
|
16
|
+
#include <memory>
|
|
15
17
|
#include <optional>
|
|
16
18
|
|
|
17
19
|
#include <faiss/impl/FaissAssert.h>
|
|
20
|
+
#include <faiss/impl/RaBitQUtils.h>
|
|
18
21
|
#include <faiss/impl/io.h>
|
|
19
22
|
#include <faiss/utils/hamming.h>
|
|
20
23
|
|
|
21
24
|
#include <faiss/invlists/InvertedListsIOHook.h>
|
|
22
25
|
|
|
26
|
+
#include <faiss/invlists/BlockInvertedLists.h>
|
|
27
|
+
|
|
23
28
|
#include <faiss/Index2Layer.h>
|
|
24
29
|
#include <faiss/IndexAdditiveQuantizer.h>
|
|
25
30
|
#include <faiss/IndexAdditiveQuantizerFastScan.h>
|
|
@@ -205,34 +210,41 @@ void read_xb_vector(VectorT& target, IOReader* f) {
|
|
|
205
210
|
* Read
|
|
206
211
|
**************************************************************/
|
|
207
212
|
|
|
208
|
-
void read_index_header(Index
|
|
209
|
-
READ1(idx
|
|
210
|
-
READ1(idx
|
|
213
|
+
static void read_index_header(Index& idx, IOReader* f) {
|
|
214
|
+
READ1(idx.d);
|
|
215
|
+
READ1(idx.ntotal);
|
|
216
|
+
FAISS_CHECK_RANGE(idx.d, 0, (1 << 20) + 1);
|
|
217
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
218
|
+
idx.ntotal >= 0,
|
|
219
|
+
"invalid ntotal %" PRId64 " read from index",
|
|
220
|
+
(int64_t)idx.ntotal);
|
|
211
221
|
idx_t dummy;
|
|
212
222
|
READ1(dummy);
|
|
213
223
|
READ1(dummy);
|
|
214
|
-
READ1(idx
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
224
|
+
READ1(idx.is_trained);
|
|
225
|
+
int metric_type_int;
|
|
226
|
+
READ1(metric_type_int);
|
|
227
|
+
idx.metric_type = metric_type_from_int(metric_type_int);
|
|
228
|
+
if (idx.metric_type > 1) {
|
|
229
|
+
READ1(idx.metric_arg);
|
|
218
230
|
}
|
|
219
|
-
idx
|
|
231
|
+
idx.verbose = false;
|
|
220
232
|
}
|
|
221
233
|
|
|
222
|
-
VectorTransform
|
|
234
|
+
std::unique_ptr<VectorTransform> read_VectorTransform_up(IOReader* f) {
|
|
223
235
|
uint32_t h;
|
|
224
236
|
READ1(h);
|
|
225
|
-
VectorTransform
|
|
237
|
+
std::unique_ptr<VectorTransform> vt;
|
|
226
238
|
|
|
227
239
|
if (h == fourcc("rrot") || h == fourcc("PCAm") || h == fourcc("LTra") ||
|
|
228
240
|
h == fourcc("PcAm") || h == fourcc("Viqm") || h == fourcc("Pcam")) {
|
|
229
|
-
LinearTransform
|
|
241
|
+
std::unique_ptr<LinearTransform> lt;
|
|
230
242
|
if (h == fourcc("rrot")) {
|
|
231
|
-
lt =
|
|
243
|
+
lt = std::make_unique<RandomRotationMatrix>();
|
|
232
244
|
} else if (
|
|
233
245
|
h == fourcc("PCAm") || h == fourcc("PcAm") ||
|
|
234
246
|
h == fourcc("Pcam")) {
|
|
235
|
-
|
|
247
|
+
auto pca = std::make_unique<PCAMatrix>();
|
|
236
248
|
READ1(pca->eigen_power);
|
|
237
249
|
if (h == fourcc("Pcam")) {
|
|
238
250
|
READ1(pca->epsilon);
|
|
@@ -244,14 +256,14 @@ VectorTransform* read_VectorTransform(IOReader* f) {
|
|
|
244
256
|
READVECTOR(pca->mean);
|
|
245
257
|
READVECTOR(pca->eigenvalues);
|
|
246
258
|
READVECTOR(pca->PCAMat);
|
|
247
|
-
lt = pca;
|
|
259
|
+
lt = std::move(pca);
|
|
248
260
|
} else if (h == fourcc("Viqm")) {
|
|
249
|
-
|
|
261
|
+
auto itqm = std::make_unique<ITQMatrix>();
|
|
250
262
|
READ1(itqm->max_iter);
|
|
251
263
|
READ1(itqm->seed);
|
|
252
|
-
lt = itqm;
|
|
264
|
+
lt = std::move(itqm);
|
|
253
265
|
} else if (h == fourcc("LTra")) {
|
|
254
|
-
lt =
|
|
266
|
+
lt = std::make_unique<LinearTransform>();
|
|
255
267
|
}
|
|
256
268
|
READ1(lt->have_bias);
|
|
257
269
|
READVECTOR(lt->A);
|
|
@@ -259,38 +271,43 @@ VectorTransform* read_VectorTransform(IOReader* f) {
|
|
|
259
271
|
FAISS_THROW_IF_NOT(lt->A.size() >= lt->d_in * lt->d_out);
|
|
260
272
|
FAISS_THROW_IF_NOT(!lt->have_bias || lt->b.size() >= lt->d_out);
|
|
261
273
|
lt->set_is_orthonormal();
|
|
262
|
-
vt = lt;
|
|
274
|
+
vt = std::move(lt);
|
|
263
275
|
} else if (h == fourcc("RmDT")) {
|
|
264
|
-
|
|
276
|
+
auto rdt = std::make_unique<RemapDimensionsTransform>();
|
|
265
277
|
READVECTOR(rdt->map);
|
|
266
|
-
vt = rdt;
|
|
278
|
+
vt = std::move(rdt);
|
|
267
279
|
} else if (h == fourcc("VNrm")) {
|
|
268
|
-
|
|
280
|
+
auto nt = std::make_unique<NormalizationTransform>();
|
|
269
281
|
READ1(nt->norm);
|
|
270
|
-
vt = nt;
|
|
282
|
+
vt = std::move(nt);
|
|
271
283
|
} else if (h == fourcc("VCnt")) {
|
|
272
|
-
|
|
284
|
+
auto ct = std::make_unique<CenteringTransform>();
|
|
273
285
|
READVECTOR(ct->mean);
|
|
274
|
-
vt = ct;
|
|
286
|
+
vt = std::move(ct);
|
|
275
287
|
} else if (h == fourcc("Viqt")) {
|
|
276
|
-
|
|
288
|
+
auto itqt = std::make_unique<ITQTransform>();
|
|
277
289
|
|
|
278
290
|
READVECTOR(itqt->mean);
|
|
279
291
|
READ1(itqt->do_pca);
|
|
280
292
|
{
|
|
281
|
-
|
|
293
|
+
// Read, dereference, discard.
|
|
294
|
+
auto sub_vt = read_VectorTransform_up(f);
|
|
295
|
+
ITQMatrix* itqm = dynamic_cast<ITQMatrix*>(sub_vt.get());
|
|
282
296
|
FAISS_THROW_IF_NOT(itqm);
|
|
283
297
|
itqt->itq = *itqm;
|
|
284
|
-
delete itqm;
|
|
285
298
|
}
|
|
286
299
|
{
|
|
287
|
-
|
|
288
|
-
|
|
300
|
+
// Read, dereference, discard.
|
|
301
|
+
auto sub_vt = read_VectorTransform_up(f);
|
|
302
|
+
LinearTransform* pi = dynamic_cast<LinearTransform*>(sub_vt.get());
|
|
289
303
|
FAISS_THROW_IF_NOT(pi);
|
|
290
304
|
itqt->pca_then_itq = *pi;
|
|
291
|
-
delete pi;
|
|
292
305
|
}
|
|
293
|
-
vt = itqt;
|
|
306
|
+
vt = std::move(itqt);
|
|
307
|
+
} else if (h == fourcc("HRot")) {
|
|
308
|
+
auto hr = std::make_unique<HadamardRotation>();
|
|
309
|
+
READ1(hr->seed);
|
|
310
|
+
vt = std::move(hr);
|
|
294
311
|
} else {
|
|
295
312
|
FAISS_THROW_FMT(
|
|
296
313
|
"fourcc %ud (\"%s\") not recognized in %s",
|
|
@@ -301,9 +318,17 @@ VectorTransform* read_VectorTransform(IOReader* f) {
|
|
|
301
318
|
READ1(vt->d_in);
|
|
302
319
|
READ1(vt->d_out);
|
|
303
320
|
READ1(vt->is_trained);
|
|
321
|
+
if (h == fourcc("HRot")) {
|
|
322
|
+
auto* hr = dynamic_cast<HadamardRotation*>(vt.get());
|
|
323
|
+
hr->init(hr->seed);
|
|
324
|
+
}
|
|
304
325
|
return vt;
|
|
305
326
|
}
|
|
306
327
|
|
|
328
|
+
VectorTransform* read_VectorTransform(IOReader* f) {
|
|
329
|
+
return read_VectorTransform_up(f).release();
|
|
330
|
+
}
|
|
331
|
+
|
|
307
332
|
static void read_ArrayInvertedLists_sizes(
|
|
308
333
|
IOReader* f,
|
|
309
334
|
std::vector<size_t>& sizes) {
|
|
@@ -316,6 +341,10 @@ static void read_ArrayInvertedLists_sizes(
|
|
|
316
341
|
} else if (list_type == fourcc("sprs")) {
|
|
317
342
|
std::vector<size_t> idsizes;
|
|
318
343
|
READVECTOR(idsizes);
|
|
344
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
345
|
+
idsizes.size() % 2 == 0,
|
|
346
|
+
"invalid sparse inverted list size: %zd (must be even)",
|
|
347
|
+
idsizes.size());
|
|
319
348
|
for (size_t j = 0; j < idsizes.size(); j += 2) {
|
|
320
349
|
FAISS_THROW_IF_NOT(idsizes[j] < sizes.size());
|
|
321
350
|
sizes[idsizes[j]] = idsizes[j + 1];
|
|
@@ -328,7 +357,9 @@ static void read_ArrayInvertedLists_sizes(
|
|
|
328
357
|
}
|
|
329
358
|
}
|
|
330
359
|
|
|
331
|
-
InvertedLists
|
|
360
|
+
std::unique_ptr<InvertedLists> read_InvertedLists_up(
|
|
361
|
+
IOReader* f,
|
|
362
|
+
int io_flags) {
|
|
332
363
|
uint32_t h;
|
|
333
364
|
READ1(h);
|
|
334
365
|
if (h == fourcc("il00")) {
|
|
@@ -341,7 +372,8 @@ InvertedLists* read_InvertedLists(IOReader* f, int io_flags) {
|
|
|
341
372
|
READ1(nlist);
|
|
342
373
|
READ1(code_size);
|
|
343
374
|
READ1(n_levels);
|
|
344
|
-
auto ailp =
|
|
375
|
+
auto ailp = std::make_unique<ArrayInvertedListsPanorama>(
|
|
376
|
+
nlist, code_size, n_levels);
|
|
345
377
|
std::vector<size_t> sizes(nlist);
|
|
346
378
|
read_ArrayInvertedLists_sizes(f, sizes);
|
|
347
379
|
for (size_t i = 0; i < nlist; i++) {
|
|
@@ -365,7 +397,7 @@ InvertedLists* read_InvertedLists(IOReader* f, int io_flags) {
|
|
|
365
397
|
}
|
|
366
398
|
return ailp;
|
|
367
399
|
} else if (h == fourcc("ilar") && !(io_flags & IO_FLAG_SKIP_IVF_DATA)) {
|
|
368
|
-
auto ails =
|
|
400
|
+
auto ails = std::make_unique<ArrayInvertedLists>(0, 0);
|
|
369
401
|
READ1(ails->nlist);
|
|
370
402
|
READ1(ails->code_size);
|
|
371
403
|
ails->ids.resize(ails->nlist);
|
|
@@ -374,13 +406,17 @@ InvertedLists* read_InvertedLists(IOReader* f, int io_flags) {
|
|
|
374
406
|
read_ArrayInvertedLists_sizes(f, sizes);
|
|
375
407
|
for (size_t i = 0; i < ails->nlist; i++) {
|
|
376
408
|
ails->ids[i].resize(sizes[i]);
|
|
377
|
-
ails->codes[i].resize(
|
|
409
|
+
ails->codes[i].resize(mul_no_overflow(
|
|
410
|
+
sizes[i], ails->code_size, "inverted list codes"));
|
|
378
411
|
}
|
|
379
412
|
for (size_t i = 0; i < ails->nlist; i++) {
|
|
380
413
|
size_t n = ails->ids[i].size();
|
|
381
414
|
if (n > 0) {
|
|
382
415
|
read_vector_with_known_size(
|
|
383
|
-
ails->codes[i],
|
|
416
|
+
ails->codes[i],
|
|
417
|
+
f,
|
|
418
|
+
mul_no_overflow(
|
|
419
|
+
n, ails->code_size, "inverted list codes"));
|
|
384
420
|
read_vector_with_known_size(ails->ids[i], f, n);
|
|
385
421
|
}
|
|
386
422
|
}
|
|
@@ -396,132 +432,150 @@ InvertedLists* read_InvertedLists(IOReader* f, int io_flags) {
|
|
|
396
432
|
READ1(code_size);
|
|
397
433
|
std::vector<size_t> sizes(nlist);
|
|
398
434
|
read_ArrayInvertedLists_sizes(f, sizes);
|
|
399
|
-
return
|
|
400
|
-
|
|
435
|
+
return std::unique_ptr<InvertedLists>(
|
|
436
|
+
InvertedListsIOHook::lookup(h2)->read_ArrayInvertedLists(
|
|
437
|
+
f, io_flags, nlist, code_size, sizes));
|
|
401
438
|
} else {
|
|
402
|
-
return
|
|
439
|
+
return std::unique_ptr<InvertedLists>(
|
|
440
|
+
InvertedListsIOHook::lookup(h)->read(f, io_flags));
|
|
403
441
|
}
|
|
404
442
|
}
|
|
405
443
|
|
|
406
|
-
|
|
407
|
-
|
|
444
|
+
InvertedLists* read_InvertedLists(IOReader* f, int io_flags) {
|
|
445
|
+
return read_InvertedLists_up(f, io_flags).release();
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
void read_InvertedLists(IndexIVF& ivf, IOReader* f, int io_flags) {
|
|
449
|
+
auto ils = read_InvertedLists_up(f, io_flags);
|
|
408
450
|
if (ils) {
|
|
409
|
-
FAISS_THROW_IF_NOT(ils->nlist == ivf
|
|
451
|
+
FAISS_THROW_IF_NOT(ils->nlist == ivf.nlist);
|
|
410
452
|
FAISS_THROW_IF_NOT(
|
|
411
453
|
ils->code_size == InvertedLists::INVALID_CODE_SIZE ||
|
|
412
|
-
ils->code_size == ivf
|
|
454
|
+
ils->code_size == ivf.code_size);
|
|
413
455
|
}
|
|
414
|
-
ivf
|
|
415
|
-
ivf
|
|
456
|
+
ivf.invlists = ils.release();
|
|
457
|
+
ivf.own_invlists = true;
|
|
416
458
|
}
|
|
417
459
|
|
|
418
460
|
void read_ProductQuantizer(ProductQuantizer* pq, IOReader* f) {
|
|
419
461
|
READ1(pq->d);
|
|
420
462
|
READ1(pq->M);
|
|
421
463
|
READ1(pq->nbits);
|
|
464
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
465
|
+
pq->M > 0, "invalid ProductQuantizer M=%zd (must be > 0)", pq->M);
|
|
422
466
|
pq->set_derived_values();
|
|
423
467
|
READVECTOR(pq->centroids);
|
|
424
468
|
}
|
|
425
469
|
|
|
426
|
-
static void read_ResidualQuantizer_old(ResidualQuantizer
|
|
427
|
-
READ1(rq
|
|
428
|
-
READ1(rq
|
|
429
|
-
READVECTOR(rq
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
READ1(rq
|
|
436
|
-
READ1(rq
|
|
437
|
-
rq
|
|
470
|
+
static void read_ResidualQuantizer_old(ResidualQuantizer& rq, IOReader* f) {
|
|
471
|
+
READ1(rq.d);
|
|
472
|
+
READ1(rq.M);
|
|
473
|
+
READVECTOR(rq.nbits);
|
|
474
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
475
|
+
rq.nbits.size() == rq.M,
|
|
476
|
+
"ResidualQuantizer nbits size %zd != M %zd",
|
|
477
|
+
rq.nbits.size(),
|
|
478
|
+
rq.M);
|
|
479
|
+
READ1(rq.is_trained);
|
|
480
|
+
READ1(rq.train_type);
|
|
481
|
+
READ1(rq.max_beam_size);
|
|
482
|
+
READVECTOR(rq.codebooks);
|
|
483
|
+
READ1(rq.search_type);
|
|
484
|
+
READ1(rq.norm_min);
|
|
485
|
+
READ1(rq.norm_max);
|
|
486
|
+
rq.set_derived_values();
|
|
438
487
|
}
|
|
439
488
|
|
|
440
|
-
static void read_AdditiveQuantizer(AdditiveQuantizer
|
|
441
|
-
READ1(aq
|
|
442
|
-
READ1(aq
|
|
443
|
-
READVECTOR(aq
|
|
444
|
-
READ1(aq
|
|
445
|
-
READVECTOR(aq
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
aq
|
|
489
|
+
static void read_AdditiveQuantizer(AdditiveQuantizer& aq, IOReader* f) {
|
|
490
|
+
READ1(aq.d);
|
|
491
|
+
READ1(aq.M);
|
|
492
|
+
READVECTOR(aq.nbits);
|
|
493
|
+
READ1(aq.is_trained);
|
|
494
|
+
READVECTOR(aq.codebooks);
|
|
495
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
496
|
+
aq.nbits.size() == aq.M,
|
|
497
|
+
"AdditiveQuantizer nbits size %zd != M %zd",
|
|
498
|
+
aq.nbits.size(),
|
|
499
|
+
aq.M);
|
|
500
|
+
READ1(aq.search_type);
|
|
501
|
+
READ1(aq.norm_min);
|
|
502
|
+
READ1(aq.norm_max);
|
|
503
|
+
if (aq.search_type == AdditiveQuantizer::ST_norm_cqint8 ||
|
|
504
|
+
aq.search_type == AdditiveQuantizer::ST_norm_cqint4 ||
|
|
505
|
+
aq.search_type == AdditiveQuantizer::ST_norm_lsq2x4 ||
|
|
506
|
+
aq.search_type == AdditiveQuantizer::ST_norm_rq2x4) {
|
|
507
|
+
read_xb_vector(aq.qnorm.codes, f);
|
|
508
|
+
aq.qnorm.ntotal = aq.qnorm.codes.size() / 4;
|
|
509
|
+
aq.qnorm.update_permutation();
|
|
456
510
|
}
|
|
457
511
|
|
|
458
|
-
if (aq
|
|
459
|
-
aq
|
|
460
|
-
READVECTOR(aq
|
|
512
|
+
if (aq.search_type == AdditiveQuantizer::ST_norm_lsq2x4 ||
|
|
513
|
+
aq.search_type == AdditiveQuantizer::ST_norm_rq2x4) {
|
|
514
|
+
READVECTOR(aq.norm_tabs);
|
|
461
515
|
}
|
|
462
516
|
|
|
463
|
-
aq
|
|
517
|
+
aq.set_derived_values();
|
|
464
518
|
}
|
|
465
519
|
|
|
466
520
|
static void read_ResidualQuantizer(
|
|
467
|
-
ResidualQuantizer
|
|
521
|
+
ResidualQuantizer& rq,
|
|
468
522
|
IOReader* f,
|
|
469
523
|
int io_flags) {
|
|
470
524
|
read_AdditiveQuantizer(rq, f);
|
|
471
|
-
READ1(rq
|
|
472
|
-
READ1(rq
|
|
473
|
-
if ((rq
|
|
525
|
+
READ1(rq.train_type);
|
|
526
|
+
READ1(rq.max_beam_size);
|
|
527
|
+
if ((rq.train_type & ResidualQuantizer::Skip_codebook_tables) ||
|
|
474
528
|
(io_flags & IO_FLAG_SKIP_PRECOMPUTE_TABLE)) {
|
|
475
529
|
// don't precompute the tables
|
|
476
530
|
} else {
|
|
477
|
-
rq
|
|
531
|
+
rq.compute_codebook_tables();
|
|
478
532
|
}
|
|
479
533
|
}
|
|
480
534
|
|
|
481
|
-
static void read_LocalSearchQuantizer(LocalSearchQuantizer
|
|
535
|
+
static void read_LocalSearchQuantizer(LocalSearchQuantizer& lsq, IOReader* f) {
|
|
482
536
|
read_AdditiveQuantizer(lsq, f);
|
|
483
|
-
READ1(lsq
|
|
484
|
-
READ1(lsq
|
|
485
|
-
READ1(lsq
|
|
486
|
-
READ1(lsq
|
|
487
|
-
READ1(lsq
|
|
488
|
-
READ1(lsq
|
|
489
|
-
READ1(lsq
|
|
490
|
-
READ1(lsq
|
|
491
|
-
READ1(lsq
|
|
492
|
-
READ1(lsq
|
|
493
|
-
READ1(lsq
|
|
537
|
+
READ1(lsq.K);
|
|
538
|
+
READ1(lsq.train_iters);
|
|
539
|
+
READ1(lsq.encode_ils_iters);
|
|
540
|
+
READ1(lsq.train_ils_iters);
|
|
541
|
+
READ1(lsq.icm_iters);
|
|
542
|
+
READ1(lsq.p);
|
|
543
|
+
READ1(lsq.lambd);
|
|
544
|
+
READ1(lsq.chunk_size);
|
|
545
|
+
READ1(lsq.random_seed);
|
|
546
|
+
READ1(lsq.nperts);
|
|
547
|
+
READ1(lsq.update_codebooks_with_double);
|
|
494
548
|
}
|
|
495
549
|
|
|
496
550
|
static void read_ProductAdditiveQuantizer(
|
|
497
|
-
ProductAdditiveQuantizer
|
|
551
|
+
ProductAdditiveQuantizer& paq,
|
|
498
552
|
IOReader* f) {
|
|
499
553
|
read_AdditiveQuantizer(paq, f);
|
|
500
|
-
READ1(paq
|
|
554
|
+
READ1(paq.nsplits);
|
|
501
555
|
}
|
|
502
556
|
|
|
503
557
|
static void read_ProductResidualQuantizer(
|
|
504
|
-
ProductResidualQuantizer
|
|
558
|
+
ProductResidualQuantizer& prq,
|
|
505
559
|
IOReader* f,
|
|
506
560
|
int io_flags) {
|
|
507
561
|
read_ProductAdditiveQuantizer(prq, f);
|
|
508
562
|
|
|
509
|
-
for (size_t i = 0; i < prq
|
|
510
|
-
auto rq =
|
|
511
|
-
read_ResidualQuantizer(rq, f, io_flags);
|
|
512
|
-
prq
|
|
563
|
+
for (size_t i = 0; i < prq.nsplits; i++) {
|
|
564
|
+
auto rq = std::make_unique<ResidualQuantizer>();
|
|
565
|
+
read_ResidualQuantizer(*rq, f, io_flags);
|
|
566
|
+
prq.quantizers.push_back(rq.release());
|
|
513
567
|
}
|
|
514
568
|
}
|
|
515
569
|
|
|
516
570
|
static void read_ProductLocalSearchQuantizer(
|
|
517
|
-
ProductLocalSearchQuantizer
|
|
571
|
+
ProductLocalSearchQuantizer& plsq,
|
|
518
572
|
IOReader* f) {
|
|
519
573
|
read_ProductAdditiveQuantizer(plsq, f);
|
|
520
574
|
|
|
521
|
-
for (size_t i = 0; i < plsq
|
|
522
|
-
auto lsq =
|
|
523
|
-
read_LocalSearchQuantizer(lsq, f);
|
|
524
|
-
plsq
|
|
575
|
+
for (size_t i = 0; i < plsq.nsplits; i++) {
|
|
576
|
+
auto lsq = std::make_unique<LocalSearchQuantizer>();
|
|
577
|
+
read_LocalSearchQuantizer(*lsq, f);
|
|
578
|
+
plsq.quantizers.push_back(lsq.release());
|
|
525
579
|
}
|
|
526
580
|
}
|
|
527
581
|
|
|
@@ -535,97 +589,237 @@ void read_ScalarQuantizer(ScalarQuantizer* ivsc, IOReader* f) {
|
|
|
535
589
|
ivsc->set_derived_sizes();
|
|
536
590
|
}
|
|
537
591
|
|
|
538
|
-
static void
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
592
|
+
static void validate_HNSW(const HNSW& hnsw) {
|
|
593
|
+
size_t ntotal = hnsw.levels.size();
|
|
594
|
+
size_t nb_neighbors_size = hnsw.neighbors.size();
|
|
595
|
+
|
|
596
|
+
// cum_nneighbor_per_level must be non-empty and monotonically
|
|
597
|
+
// non-decreasing, starting at 0
|
|
598
|
+
if (!hnsw.cum_nneighbor_per_level.empty()) {
|
|
599
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
600
|
+
hnsw.cum_nneighbor_per_level[0] == 0,
|
|
601
|
+
"HNSW cum_nneighbor_per_level[0] = %d, expected 0",
|
|
602
|
+
hnsw.cum_nneighbor_per_level[0]);
|
|
603
|
+
for (size_t i = 1; i < hnsw.cum_nneighbor_per_level.size(); i++) {
|
|
604
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
605
|
+
hnsw.cum_nneighbor_per_level[i] >=
|
|
606
|
+
hnsw.cum_nneighbor_per_level[i - 1],
|
|
607
|
+
"HNSW cum_nneighbor_per_level not monotonic at %zd: "
|
|
608
|
+
"%d < %d",
|
|
609
|
+
i,
|
|
610
|
+
hnsw.cum_nneighbor_per_level[i],
|
|
611
|
+
hnsw.cum_nneighbor_per_level[i - 1]);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// every levels[i] must be a valid index into cum_nneighbor_per_level
|
|
616
|
+
size_t cum_size = hnsw.cum_nneighbor_per_level.size();
|
|
617
|
+
for (size_t i = 0; i < ntotal; i++) {
|
|
618
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
619
|
+
hnsw.levels[i] >= 0 &&
|
|
620
|
+
static_cast<size_t>(hnsw.levels[i]) < cum_size,
|
|
621
|
+
"HNSW levels[%zd] = %d out of range [0, %zd)",
|
|
622
|
+
i,
|
|
623
|
+
hnsw.levels[i],
|
|
624
|
+
cum_size);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// offsets must have size ntotal + 1, be monotonically non-decreasing,
|
|
628
|
+
// and all values must be <= neighbors.size()
|
|
629
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
630
|
+
hnsw.offsets.size() == ntotal + 1,
|
|
631
|
+
"HNSW offsets size %zd != levels size %zd + 1",
|
|
632
|
+
hnsw.offsets.size(),
|
|
633
|
+
ntotal);
|
|
634
|
+
for (size_t i = 0; i < hnsw.offsets.size(); i++) {
|
|
635
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
636
|
+
hnsw.offsets[i] <= nb_neighbors_size,
|
|
637
|
+
"HNSW offsets[%zd] = %zd > neighbors.size() = %zd",
|
|
638
|
+
i,
|
|
639
|
+
hnsw.offsets[i],
|
|
640
|
+
nb_neighbors_size);
|
|
641
|
+
if (i > 0) {
|
|
642
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
643
|
+
hnsw.offsets[i] ==
|
|
644
|
+
hnsw.offsets[i - 1] +
|
|
645
|
+
hnsw.cum_nneighbor_per_level
|
|
646
|
+
[hnsw.levels[i - 1]],
|
|
647
|
+
"HNSW offsets not increasing by cum_neighbor_per_level at %zd: %zd + %d != %zd",
|
|
648
|
+
i,
|
|
649
|
+
hnsw.offsets[i - 1],
|
|
650
|
+
hnsw.cum_nneighbor_per_level[hnsw.levels[i - 1]],
|
|
651
|
+
hnsw.offsets[i]);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// max_level must be valid
|
|
656
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
657
|
+
hnsw.max_level < (int)hnsw.cum_nneighbor_per_level.size(),
|
|
658
|
+
"HNSW max_level %d >= cum_nneighbor_per_level size %zd",
|
|
659
|
+
hnsw.max_level,
|
|
660
|
+
hnsw.cum_nneighbor_per_level.size());
|
|
661
|
+
|
|
662
|
+
// entry_point must be -1 (empty) or a valid node id
|
|
663
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
664
|
+
hnsw.entry_point >= -1 && hnsw.entry_point < (int)ntotal,
|
|
665
|
+
"HNSW entry_point %d out of range [-1, %zd)",
|
|
666
|
+
(int)hnsw.entry_point,
|
|
667
|
+
ntotal);
|
|
668
|
+
|
|
669
|
+
// All neighbor ids must be -1 or in [0, ntotal)
|
|
670
|
+
for (size_t i = 0; i < nb_neighbors_size; i++) {
|
|
671
|
+
auto id = hnsw.neighbors[i];
|
|
672
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
673
|
+
id >= -1 && id < (int)ntotal,
|
|
674
|
+
"HNSW neighbors[%zd] = %d out of range [-1, %zd)",
|
|
675
|
+
i,
|
|
676
|
+
(int)id,
|
|
677
|
+
ntotal);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// For each node, verify that its level is valid and that
|
|
681
|
+
// offsets[i] + cum_nneighbor_per_level[levels[i]] <= neighbors.size().
|
|
682
|
+
// This ensures neighbor_range() can never produce an out-of-bounds offset
|
|
683
|
+
// into neighbors.
|
|
684
|
+
int cum_levels = (int)hnsw.cum_nneighbor_per_level.size();
|
|
685
|
+
for (size_t i = 0; i < ntotal; i++) {
|
|
686
|
+
int level = hnsw.levels[i];
|
|
687
|
+
FAISS_CHECK_RANGE(level, 1, cum_levels + 1);
|
|
688
|
+
size_t end = hnsw.offsets[i] + hnsw.cum_nneighbor_per_level[level];
|
|
689
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
690
|
+
end <= nb_neighbors_size,
|
|
691
|
+
"HNSW neighbor range overflow for node %zd: "
|
|
692
|
+
"offsets[%zd] (%zd) + cum_nneighbor_per_level[%d] (%d) "
|
|
693
|
+
"= %zd > neighbors.size() (%zd)",
|
|
694
|
+
i,
|
|
695
|
+
i,
|
|
696
|
+
hnsw.offsets[i],
|
|
697
|
+
level,
|
|
698
|
+
hnsw.cum_nneighbor_per_level[level],
|
|
699
|
+
end,
|
|
700
|
+
nb_neighbors_size);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
544
703
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
704
|
+
static void read_HNSW(HNSW& hnsw, IOReader* f) {
|
|
705
|
+
READVECTOR(hnsw.assign_probas);
|
|
706
|
+
READVECTOR(hnsw.cum_nneighbor_per_level);
|
|
707
|
+
READVECTOR(hnsw.levels);
|
|
708
|
+
READVECTOR(hnsw.offsets);
|
|
709
|
+
read_vector(hnsw.neighbors, f);
|
|
710
|
+
|
|
711
|
+
READ1(hnsw.entry_point);
|
|
712
|
+
READ1(hnsw.max_level);
|
|
713
|
+
READ1(hnsw.efConstruction);
|
|
714
|
+
READ1(hnsw.efSearch);
|
|
549
715
|
|
|
550
716
|
// // deprecated field
|
|
551
|
-
// READ1(hnsw
|
|
717
|
+
// READ1(hnsw.upper_beam);
|
|
552
718
|
READ1_DUMMY(int)
|
|
719
|
+
|
|
720
|
+
validate_HNSW(hnsw);
|
|
553
721
|
}
|
|
554
722
|
|
|
555
|
-
static void read_NSG(NSG
|
|
556
|
-
READ1(nsg
|
|
557
|
-
READ1(nsg
|
|
558
|
-
READ1(nsg
|
|
559
|
-
READ1(nsg
|
|
560
|
-
READ1(nsg
|
|
561
|
-
READ1(nsg
|
|
562
|
-
READ1(nsg
|
|
723
|
+
static void read_NSG(NSG& nsg, IOReader* f) {
|
|
724
|
+
READ1(nsg.ntotal);
|
|
725
|
+
READ1(nsg.R);
|
|
726
|
+
READ1(nsg.L);
|
|
727
|
+
READ1(nsg.C);
|
|
728
|
+
READ1(nsg.search_L);
|
|
729
|
+
READ1(nsg.enterpoint);
|
|
730
|
+
READ1(nsg.is_built);
|
|
563
731
|
|
|
564
|
-
|
|
732
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
733
|
+
nsg.ntotal >= 0, "invalid NSG ntotal %d", nsg.ntotal);
|
|
734
|
+
|
|
735
|
+
if (!nsg.is_built) {
|
|
565
736
|
return;
|
|
566
737
|
}
|
|
567
738
|
|
|
568
739
|
constexpr int EMPTY_ID = -1;
|
|
569
|
-
int N = nsg
|
|
570
|
-
int R = nsg
|
|
571
|
-
|
|
740
|
+
int N = nsg.ntotal;
|
|
741
|
+
int R = nsg.R;
|
|
742
|
+
|
|
743
|
+
auto& graph = nsg.final_graph;
|
|
572
744
|
graph = std::make_shared<nsg::Graph<int>>(N, R);
|
|
573
|
-
std::fill_n(graph->data, N * R, EMPTY_ID);
|
|
745
|
+
std::fill_n(graph->data, (size_t)N * R, EMPTY_ID);
|
|
574
746
|
|
|
575
747
|
for (int i = 0; i < N; i++) {
|
|
576
|
-
|
|
748
|
+
int j;
|
|
749
|
+
for (j = 0; j < R; j++) {
|
|
577
750
|
int id;
|
|
578
751
|
READ1(id);
|
|
579
752
|
if (id != EMPTY_ID) {
|
|
753
|
+
FAISS_CHECK_RANGE(id, 0, N);
|
|
580
754
|
graph->at(i, j) = id;
|
|
581
755
|
} else {
|
|
582
756
|
break;
|
|
583
757
|
}
|
|
584
758
|
}
|
|
759
|
+
if (j == R) {
|
|
760
|
+
// All R neighbor slots were filled; consume the trailing
|
|
761
|
+
// EMPTY_ID sentinel that write_NSG always appends.
|
|
762
|
+
int sentinel;
|
|
763
|
+
READ1(sentinel);
|
|
764
|
+
FAISS_THROW_IF_NOT(sentinel == EMPTY_ID);
|
|
765
|
+
}
|
|
585
766
|
}
|
|
767
|
+
|
|
768
|
+
// enterpoint must be a valid node id
|
|
769
|
+
FAISS_CHECK_RANGE(nsg.enterpoint, 0, N);
|
|
586
770
|
}
|
|
587
771
|
|
|
588
|
-
static void read_NNDescent(NNDescent
|
|
589
|
-
READ1(nnd
|
|
590
|
-
READ1(nnd
|
|
591
|
-
READ1(nnd
|
|
592
|
-
READ1(nnd
|
|
593
|
-
READ1(nnd
|
|
594
|
-
READ1(nnd
|
|
595
|
-
READ1(nnd
|
|
596
|
-
READ1(nnd
|
|
597
|
-
READ1(nnd
|
|
598
|
-
READ1(nnd
|
|
599
|
-
|
|
600
|
-
|
|
772
|
+
static void read_NNDescent(NNDescent& nnd, IOReader* f) {
|
|
773
|
+
READ1(nnd.ntotal);
|
|
774
|
+
READ1(nnd.d);
|
|
775
|
+
READ1(nnd.K);
|
|
776
|
+
READ1(nnd.S);
|
|
777
|
+
READ1(nnd.R);
|
|
778
|
+
READ1(nnd.L);
|
|
779
|
+
READ1(nnd.iter);
|
|
780
|
+
READ1(nnd.search_L);
|
|
781
|
+
READ1(nnd.random_seed);
|
|
782
|
+
READ1(nnd.has_built);
|
|
783
|
+
|
|
784
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
785
|
+
nnd.ntotal >= 0, "invalid NNDescent ntotal %d", nnd.ntotal);
|
|
786
|
+
|
|
787
|
+
READVECTOR(nnd.final_graph);
|
|
601
788
|
}
|
|
602
789
|
|
|
603
|
-
ProductQuantizer
|
|
790
|
+
std::unique_ptr<ProductQuantizer> read_ProductQuantizer_up(const char* fname) {
|
|
604
791
|
FileIOReader reader(fname);
|
|
605
|
-
return
|
|
792
|
+
return read_ProductQuantizer_up(&reader);
|
|
606
793
|
}
|
|
607
794
|
|
|
608
|
-
ProductQuantizer* read_ProductQuantizer(
|
|
609
|
-
|
|
610
|
-
|
|
795
|
+
ProductQuantizer* read_ProductQuantizer(const char* fname) {
|
|
796
|
+
return read_ProductQuantizer_up(fname).release();
|
|
797
|
+
}
|
|
611
798
|
|
|
612
|
-
|
|
613
|
-
|
|
799
|
+
std::unique_ptr<ProductQuantizer> read_ProductQuantizer_up(IOReader* reader) {
|
|
800
|
+
auto pq = std::make_unique<ProductQuantizer>();
|
|
801
|
+
read_ProductQuantizer(pq.get(), reader);
|
|
614
802
|
return pq;
|
|
615
803
|
}
|
|
616
804
|
|
|
805
|
+
ProductQuantizer* read_ProductQuantizer(IOReader* reader) {
|
|
806
|
+
return read_ProductQuantizer_up(reader).release();
|
|
807
|
+
}
|
|
808
|
+
|
|
617
809
|
static void read_RaBitQuantizer(
|
|
618
|
-
RaBitQuantizer
|
|
810
|
+
RaBitQuantizer& rabitq,
|
|
619
811
|
IOReader* f,
|
|
620
812
|
bool multi_bit = true) {
|
|
621
|
-
READ1(rabitq
|
|
622
|
-
READ1(rabitq
|
|
623
|
-
|
|
813
|
+
READ1(rabitq.d);
|
|
814
|
+
READ1(rabitq.code_size);
|
|
815
|
+
int metric_type_int;
|
|
816
|
+
READ1(metric_type_int);
|
|
817
|
+
rabitq.metric_type = metric_type_from_int(metric_type_int);
|
|
624
818
|
|
|
625
819
|
if (multi_bit) {
|
|
626
|
-
READ1(rabitq
|
|
820
|
+
READ1(rabitq.nb_bits);
|
|
627
821
|
} else {
|
|
628
|
-
rabitq
|
|
822
|
+
rabitq.nb_bits = 1;
|
|
629
823
|
}
|
|
630
824
|
}
|
|
631
825
|
|
|
@@ -649,7 +843,7 @@ void read_ivf_header(
|
|
|
649
843
|
IndexIVF* ivf,
|
|
650
844
|
IOReader* f,
|
|
651
845
|
std::vector<std::vector<idx_t>>* ids) {
|
|
652
|
-
read_index_header(ivf, f);
|
|
846
|
+
read_index_header(*ivf, f);
|
|
653
847
|
READ1(ivf->nlist);
|
|
654
848
|
READ1(ivf->nprobe);
|
|
655
849
|
ivf->quantizer = read_index(f);
|
|
@@ -666,39 +860,46 @@ void read_ivf_header(
|
|
|
666
860
|
ArrayInvertedLists* set_array_invlist(
|
|
667
861
|
IndexIVF* ivf,
|
|
668
862
|
std::vector<std::vector<idx_t>>& ids) {
|
|
669
|
-
|
|
670
|
-
new ArrayInvertedLists(ivf->nlist, ivf->code_size);
|
|
863
|
+
auto ail = std::make_unique<ArrayInvertedLists>(ivf->nlist, ivf->code_size);
|
|
671
864
|
|
|
672
865
|
ail->ids.resize(ids.size());
|
|
673
866
|
for (size_t i = 0; i < ids.size(); i++) {
|
|
674
867
|
ail->ids[i] = MaybeOwnedVector<idx_t>(std::move(ids[i]));
|
|
675
868
|
}
|
|
676
869
|
|
|
677
|
-
|
|
870
|
+
ArrayInvertedLists* result = ail.get();
|
|
871
|
+
ivf->invlists = ail.release();
|
|
678
872
|
ivf->own_invlists = true;
|
|
679
|
-
return
|
|
873
|
+
return result;
|
|
680
874
|
}
|
|
681
875
|
|
|
682
|
-
static IndexIVFPQ
|
|
876
|
+
static std::unique_ptr<IndexIVFPQ> read_ivfpq(
|
|
877
|
+
IOReader* f,
|
|
878
|
+
uint32_t h,
|
|
879
|
+
int io_flags) {
|
|
683
880
|
bool legacy = h == fourcc("IvQR") || h == fourcc("IvPQ");
|
|
684
881
|
|
|
685
|
-
IndexIVFPQR* ivfpqr =
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
882
|
+
IndexIVFPQR* ivfpqr = nullptr;
|
|
883
|
+
std::unique_ptr<IndexIVFPQ> ivpq;
|
|
884
|
+
if (h == fourcc("IvQR") || h == fourcc("IwQR")) {
|
|
885
|
+
ivpq = std::make_unique<IndexIVFPQR>();
|
|
886
|
+
ivfpqr = static_cast<IndexIVFPQR*>(ivpq.get());
|
|
887
|
+
} else {
|
|
888
|
+
ivpq = std::make_unique<IndexIVFPQ>();
|
|
889
|
+
}
|
|
689
890
|
|
|
690
891
|
std::vector<std::vector<idx_t>> ids;
|
|
691
|
-
read_ivf_header(ivpq, f, legacy ? &ids : nullptr);
|
|
892
|
+
read_ivf_header(ivpq.get(), f, legacy ? &ids : nullptr);
|
|
692
893
|
READ1(ivpq->by_residual);
|
|
693
894
|
READ1(ivpq->code_size);
|
|
694
895
|
read_ProductQuantizer(&ivpq->pq, f);
|
|
695
896
|
|
|
696
897
|
if (legacy) {
|
|
697
|
-
ArrayInvertedLists* ail = set_array_invlist(ivpq, ids);
|
|
898
|
+
ArrayInvertedLists* ail = set_array_invlist(ivpq.get(), ids);
|
|
698
899
|
for (size_t i = 0; i < ail->nlist; i++)
|
|
699
900
|
READVECTOR(ail->codes[i]);
|
|
700
901
|
} else {
|
|
701
|
-
read_InvertedLists(ivpq, f, io_flags);
|
|
902
|
+
read_InvertedLists(*ivpq, f, io_flags);
|
|
702
903
|
}
|
|
703
904
|
|
|
704
905
|
if (ivpq->is_trained) {
|
|
@@ -721,47 +922,53 @@ static IndexIVFPQ* read_ivfpq(IOReader* f, uint32_t h, int io_flags) {
|
|
|
721
922
|
|
|
722
923
|
int read_old_fmt_hack = 0;
|
|
723
924
|
|
|
724
|
-
Index
|
|
725
|
-
Index
|
|
925
|
+
std::unique_ptr<Index> read_index_up(IOReader* f, int io_flags) {
|
|
926
|
+
std::unique_ptr<Index> idx;
|
|
726
927
|
uint32_t h;
|
|
727
928
|
READ1(h);
|
|
728
929
|
if (h == fourcc("null")) {
|
|
729
930
|
// denotes a missing index, useful for some cases
|
|
730
|
-
return
|
|
731
|
-
} else if (h == fourcc("IxFP")) {
|
|
931
|
+
return idx;
|
|
932
|
+
} else if (h == fourcc("IxFP") || h == fourcc("IxFp")) {
|
|
732
933
|
int d;
|
|
733
934
|
size_t n_levels, batch_size;
|
|
734
935
|
READ1(d);
|
|
735
936
|
READ1(n_levels);
|
|
937
|
+
FAISS_THROW_IF_NOT_FMT(n_levels > 0, "invalid n_levels %zd", n_levels);
|
|
736
938
|
READ1(batch_size);
|
|
737
|
-
|
|
738
|
-
|
|
939
|
+
std::unique_ptr<IndexFlatPanorama> idxp;
|
|
940
|
+
if (h == fourcc("IxFP")) {
|
|
941
|
+
idxp = std::make_unique<IndexFlatL2Panorama>(
|
|
942
|
+
d, n_levels, batch_size);
|
|
943
|
+
} else {
|
|
944
|
+
idxp = std::make_unique<IndexFlatIPPanorama>(
|
|
945
|
+
d, n_levels, batch_size);
|
|
946
|
+
}
|
|
739
947
|
READ1(idxp->ntotal);
|
|
740
948
|
READ1(idxp->is_trained);
|
|
741
949
|
READVECTOR(idxp->codes);
|
|
742
950
|
READVECTOR(idxp->cum_sums);
|
|
743
951
|
idxp->verbose = false;
|
|
744
|
-
idx = idxp;
|
|
952
|
+
idx = std::move(idxp);
|
|
745
953
|
} else if (
|
|
746
954
|
h == fourcc("IxFI") || h == fourcc("IxF2") || h == fourcc("IxFl")) {
|
|
747
|
-
IndexFlat
|
|
955
|
+
std::unique_ptr<IndexFlat> idxf;
|
|
748
956
|
if (h == fourcc("IxFI")) {
|
|
749
|
-
idxf =
|
|
957
|
+
idxf = std::make_unique<IndexFlatIP>();
|
|
750
958
|
} else if (h == fourcc("IxF2")) {
|
|
751
|
-
idxf =
|
|
959
|
+
idxf = std::make_unique<IndexFlatL2>();
|
|
752
960
|
} else {
|
|
753
|
-
idxf =
|
|
961
|
+
idxf = std::make_unique<IndexFlat>();
|
|
754
962
|
}
|
|
755
|
-
read_index_header(idxf, f);
|
|
963
|
+
read_index_header(*idxf, f);
|
|
756
964
|
idxf->code_size = idxf->d * sizeof(float);
|
|
757
965
|
read_xb_vector(idxf->codes, f);
|
|
758
966
|
FAISS_THROW_IF_NOT(
|
|
759
967
|
idxf->codes.size() == idxf->ntotal * idxf->code_size);
|
|
760
|
-
|
|
761
|
-
idx = idxf;
|
|
968
|
+
idx = std::move(idxf);
|
|
762
969
|
} else if (h == fourcc("IxHE") || h == fourcc("IxHe")) {
|
|
763
|
-
|
|
764
|
-
read_index_header(idxl, f);
|
|
970
|
+
auto idxl = std::make_unique<IndexLSH>();
|
|
971
|
+
read_index_header(*idxl, f);
|
|
765
972
|
READ1(idxl->nbits);
|
|
766
973
|
READ1(idxl->rotate_data);
|
|
767
974
|
READ1(idxl->train_thresholds);
|
|
@@ -779,23 +986,24 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
779
986
|
idxl->code_size *= 8;
|
|
780
987
|
}
|
|
781
988
|
{
|
|
782
|
-
|
|
783
|
-
|
|
989
|
+
// Read, dereference, discard.
|
|
990
|
+
auto sub_vt = read_VectorTransform_up(f);
|
|
991
|
+
RandomRotationMatrix* rrot =
|
|
992
|
+
dynamic_cast<RandomRotationMatrix*>(sub_vt.get());
|
|
784
993
|
FAISS_THROW_IF_NOT_MSG(rrot, "expected a random rotation");
|
|
785
994
|
idxl->rrot = *rrot;
|
|
786
|
-
delete rrot;
|
|
787
995
|
}
|
|
788
996
|
read_vector(idxl->codes, f);
|
|
789
997
|
FAISS_THROW_IF_NOT(
|
|
790
998
|
idxl->rrot.d_in == idxl->d && idxl->rrot.d_out == idxl->nbits);
|
|
791
999
|
FAISS_THROW_IF_NOT(
|
|
792
1000
|
idxl->codes.size() == idxl->ntotal * idxl->code_size);
|
|
793
|
-
idx = idxl;
|
|
1001
|
+
idx = std::move(idxl);
|
|
794
1002
|
} else if (
|
|
795
1003
|
h == fourcc("IxPQ") || h == fourcc("IxPo") || h == fourcc("IxPq")) {
|
|
796
1004
|
// IxPQ and IxPo were merged into the same IndexPQ object
|
|
797
|
-
|
|
798
|
-
read_index_header(idxp, f);
|
|
1005
|
+
auto idxp = std::make_unique<IndexPQ>();
|
|
1006
|
+
read_index_header(*idxp, f);
|
|
799
1007
|
read_ProductQuantizer(&idxp->pq, f);
|
|
800
1008
|
idxp->code_size = idxp->pq.code_size;
|
|
801
1009
|
read_vector(idxp->codes, f);
|
|
@@ -810,43 +1018,43 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
810
1018
|
if (h == fourcc("IxPQ") || h == fourcc("IxPo")) {
|
|
811
1019
|
idxp->metric_type = METRIC_L2;
|
|
812
1020
|
}
|
|
813
|
-
idx = idxp;
|
|
1021
|
+
idx = std::move(idxp);
|
|
814
1022
|
} else if (h == fourcc("IxRQ") || h == fourcc("IxRq")) {
|
|
815
|
-
|
|
816
|
-
read_index_header(idxr, f);
|
|
1023
|
+
auto idxr = std::make_unique<IndexResidualQuantizer>();
|
|
1024
|
+
read_index_header(*idxr, f);
|
|
817
1025
|
if (h == fourcc("IxRQ")) {
|
|
818
|
-
read_ResidualQuantizer_old(
|
|
1026
|
+
read_ResidualQuantizer_old(idxr->rq, f);
|
|
819
1027
|
} else {
|
|
820
|
-
read_ResidualQuantizer(
|
|
1028
|
+
read_ResidualQuantizer(idxr->rq, f, io_flags);
|
|
821
1029
|
}
|
|
822
1030
|
READ1(idxr->code_size);
|
|
823
1031
|
read_vector(idxr->codes, f);
|
|
824
|
-
idx = idxr;
|
|
1032
|
+
idx = std::move(idxr);
|
|
825
1033
|
} else if (h == fourcc("IxLS")) {
|
|
826
|
-
auto idxr =
|
|
827
|
-
read_index_header(idxr, f);
|
|
828
|
-
read_LocalSearchQuantizer(
|
|
1034
|
+
auto idxr = std::make_unique<IndexLocalSearchQuantizer>();
|
|
1035
|
+
read_index_header(*idxr, f);
|
|
1036
|
+
read_LocalSearchQuantizer(idxr->lsq, f);
|
|
829
1037
|
READ1(idxr->code_size);
|
|
830
1038
|
read_vector(idxr->codes, f);
|
|
831
|
-
idx = idxr;
|
|
1039
|
+
idx = std::move(idxr);
|
|
832
1040
|
} else if (h == fourcc("IxPR")) {
|
|
833
|
-
auto idxpr =
|
|
834
|
-
read_index_header(idxpr, f);
|
|
835
|
-
read_ProductResidualQuantizer(
|
|
1041
|
+
auto idxpr = std::make_unique<IndexProductResidualQuantizer>();
|
|
1042
|
+
read_index_header(*idxpr, f);
|
|
1043
|
+
read_ProductResidualQuantizer(idxpr->prq, f, io_flags);
|
|
836
1044
|
READ1(idxpr->code_size);
|
|
837
1045
|
read_vector(idxpr->codes, f);
|
|
838
|
-
idx = idxpr;
|
|
1046
|
+
idx = std::move(idxpr);
|
|
839
1047
|
} else if (h == fourcc("IxPL")) {
|
|
840
|
-
auto idxpl =
|
|
841
|
-
read_index_header(idxpl, f);
|
|
842
|
-
read_ProductLocalSearchQuantizer(
|
|
1048
|
+
auto idxpl = std::make_unique<IndexProductLocalSearchQuantizer>();
|
|
1049
|
+
read_index_header(*idxpl, f);
|
|
1050
|
+
read_ProductLocalSearchQuantizer(idxpl->plsq, f);
|
|
843
1051
|
READ1(idxpl->code_size);
|
|
844
1052
|
read_vector(idxpl->codes, f);
|
|
845
|
-
idx = idxpl;
|
|
1053
|
+
idx = std::move(idxpl);
|
|
846
1054
|
} else if (h == fourcc("ImRQ")) {
|
|
847
|
-
|
|
848
|
-
read_index_header(idxr, f);
|
|
849
|
-
read_ResidualQuantizer(
|
|
1055
|
+
auto idxr = std::make_unique<ResidualCoarseQuantizer>();
|
|
1056
|
+
read_index_header(*idxr, f);
|
|
1057
|
+
read_ResidualQuantizer(idxr->rq, f, io_flags);
|
|
850
1058
|
READ1(idxr->beam_factor);
|
|
851
1059
|
if (io_flags & IO_FLAG_SKIP_PRECOMPUTE_TABLE) {
|
|
852
1060
|
// then we force the beam factor to -1
|
|
@@ -854,7 +1062,7 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
854
1062
|
idxr->beam_factor = -1;
|
|
855
1063
|
}
|
|
856
1064
|
idxr->set_beam_factor(idxr->beam_factor);
|
|
857
|
-
idx = idxr;
|
|
1065
|
+
idx = std::move(idxr);
|
|
858
1066
|
} else if (
|
|
859
1067
|
h == fourcc("ILfs") || h == fourcc("IRfs") || h == fourcc("IPRf") ||
|
|
860
1068
|
h == fourcc("IPLf")) {
|
|
@@ -862,29 +1070,30 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
862
1070
|
bool is_RQ = h == fourcc("IRfs");
|
|
863
1071
|
bool is_PLSQ = h == fourcc("IPLf");
|
|
864
1072
|
|
|
865
|
-
IndexAdditiveQuantizerFastScan
|
|
1073
|
+
std::unique_ptr<IndexAdditiveQuantizerFastScan> idxaqfs;
|
|
866
1074
|
if (is_LSQ) {
|
|
867
|
-
idxaqfs =
|
|
1075
|
+
idxaqfs = std::make_unique<IndexLocalSearchQuantizerFastScan>();
|
|
868
1076
|
} else if (is_RQ) {
|
|
869
|
-
idxaqfs =
|
|
1077
|
+
idxaqfs = std::make_unique<IndexResidualQuantizerFastScan>();
|
|
870
1078
|
} else if (is_PLSQ) {
|
|
871
|
-
idxaqfs =
|
|
1079
|
+
idxaqfs = std::make_unique<
|
|
1080
|
+
IndexProductLocalSearchQuantizerFastScan>();
|
|
872
1081
|
} else {
|
|
873
|
-
idxaqfs =
|
|
1082
|
+
idxaqfs = std::make_unique<IndexProductResidualQuantizerFastScan>();
|
|
874
1083
|
}
|
|
875
|
-
read_index_header(idxaqfs, f);
|
|
1084
|
+
read_index_header(*idxaqfs, f);
|
|
876
1085
|
|
|
877
1086
|
if (is_LSQ) {
|
|
878
|
-
read_LocalSearchQuantizer((LocalSearchQuantizer*)idxaqfs->aq, f);
|
|
1087
|
+
read_LocalSearchQuantizer(*(LocalSearchQuantizer*)idxaqfs->aq, f);
|
|
879
1088
|
} else if (is_RQ) {
|
|
880
1089
|
read_ResidualQuantizer(
|
|
881
|
-
(ResidualQuantizer*)idxaqfs->aq, f, io_flags);
|
|
1090
|
+
*(ResidualQuantizer*)idxaqfs->aq, f, io_flags);
|
|
882
1091
|
} else if (is_PLSQ) {
|
|
883
1092
|
read_ProductLocalSearchQuantizer(
|
|
884
|
-
(ProductLocalSearchQuantizer*)idxaqfs->aq, f);
|
|
1093
|
+
*(ProductLocalSearchQuantizer*)idxaqfs->aq, f);
|
|
885
1094
|
} else {
|
|
886
1095
|
read_ProductResidualQuantizer(
|
|
887
|
-
(ProductResidualQuantizer*)idxaqfs->aq, f, io_flags);
|
|
1096
|
+
*(ProductResidualQuantizer*)idxaqfs->aq, f, io_flags);
|
|
888
1097
|
}
|
|
889
1098
|
|
|
890
1099
|
READ1(idxaqfs->implem);
|
|
@@ -903,7 +1112,7 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
903
1112
|
READ1(idxaqfs->max_train_points);
|
|
904
1113
|
|
|
905
1114
|
READVECTOR(idxaqfs->codes);
|
|
906
|
-
idx = idxaqfs;
|
|
1115
|
+
idx = std::move(idxaqfs);
|
|
907
1116
|
} else if (
|
|
908
1117
|
h == fourcc("IVLf") || h == fourcc("IVRf") || h == fourcc("NPLf") ||
|
|
909
1118
|
h == fourcc("NPRf")) {
|
|
@@ -911,28 +1120,31 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
911
1120
|
bool is_RQ = h == fourcc("IVRf");
|
|
912
1121
|
bool is_PLSQ = h == fourcc("NPLf");
|
|
913
1122
|
|
|
914
|
-
IndexIVFAdditiveQuantizerFastScan
|
|
1123
|
+
std::unique_ptr<IndexIVFAdditiveQuantizerFastScan> ivaqfs;
|
|
915
1124
|
if (is_LSQ) {
|
|
916
|
-
ivaqfs =
|
|
1125
|
+
ivaqfs = std::make_unique<IndexIVFLocalSearchQuantizerFastScan>();
|
|
917
1126
|
} else if (is_RQ) {
|
|
918
|
-
ivaqfs =
|
|
1127
|
+
ivaqfs = std::make_unique<IndexIVFResidualQuantizerFastScan>();
|
|
919
1128
|
} else if (is_PLSQ) {
|
|
920
|
-
ivaqfs =
|
|
1129
|
+
ivaqfs = std::make_unique<
|
|
1130
|
+
IndexIVFProductLocalSearchQuantizerFastScan>();
|
|
921
1131
|
} else {
|
|
922
|
-
ivaqfs =
|
|
1132
|
+
ivaqfs = std::make_unique<
|
|
1133
|
+
IndexIVFProductResidualQuantizerFastScan>();
|
|
923
1134
|
}
|
|
924
|
-
read_ivf_header(ivaqfs, f);
|
|
1135
|
+
read_ivf_header(ivaqfs.get(), f);
|
|
925
1136
|
|
|
926
1137
|
if (is_LSQ) {
|
|
927
|
-
read_LocalSearchQuantizer((LocalSearchQuantizer*)ivaqfs->aq, f);
|
|
1138
|
+
read_LocalSearchQuantizer(*(LocalSearchQuantizer*)ivaqfs->aq, f);
|
|
928
1139
|
} else if (is_RQ) {
|
|
929
|
-
read_ResidualQuantizer(
|
|
1140
|
+
read_ResidualQuantizer(
|
|
1141
|
+
*(ResidualQuantizer*)ivaqfs->aq, f, io_flags);
|
|
930
1142
|
} else if (is_PLSQ) {
|
|
931
1143
|
read_ProductLocalSearchQuantizer(
|
|
932
|
-
(ProductLocalSearchQuantizer*)ivaqfs->aq, f);
|
|
1144
|
+
*(ProductLocalSearchQuantizer*)ivaqfs->aq, f);
|
|
933
1145
|
} else {
|
|
934
1146
|
read_ProductResidualQuantizer(
|
|
935
|
-
(ProductResidualQuantizer*)ivaqfs->aq, f, io_flags);
|
|
1147
|
+
*(ProductResidualQuantizer*)ivaqfs->aq, f, io_flags);
|
|
936
1148
|
}
|
|
937
1149
|
|
|
938
1150
|
READ1(ivaqfs->by_residual);
|
|
@@ -951,15 +1163,15 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
951
1163
|
READ1(ivaqfs->norm_scale);
|
|
952
1164
|
READ1(ivaqfs->max_train_points);
|
|
953
1165
|
|
|
954
|
-
read_InvertedLists(ivaqfs, f, io_flags);
|
|
1166
|
+
read_InvertedLists(*ivaqfs, f, io_flags);
|
|
955
1167
|
ivaqfs->init_code_packer();
|
|
956
|
-
idx = ivaqfs;
|
|
1168
|
+
idx = std::move(ivaqfs);
|
|
957
1169
|
} else if (h == fourcc("IvFl") || h == fourcc("IvFL")) { // legacy
|
|
958
|
-
|
|
1170
|
+
auto ivfl = std::make_unique<IndexIVFFlat>();
|
|
959
1171
|
std::vector<std::vector<idx_t>> ids;
|
|
960
|
-
read_ivf_header(ivfl, f, &ids);
|
|
1172
|
+
read_ivf_header(ivfl.get(), f, &ids);
|
|
961
1173
|
ivfl->code_size = ivfl->d * sizeof(float);
|
|
962
|
-
ArrayInvertedLists* ail = set_array_invlist(ivfl, ids);
|
|
1174
|
+
ArrayInvertedLists* ail = set_array_invlist(ivfl.get(), ids);
|
|
963
1175
|
|
|
964
1176
|
if (h == fourcc("IvFL")) {
|
|
965
1177
|
for (size_t i = 0; i < ivfl->nlist; i++) {
|
|
@@ -973,64 +1185,85 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
973
1185
|
memcpy(ail->codes[i].data(), vec.data(), ail->codes[i].size());
|
|
974
1186
|
}
|
|
975
1187
|
}
|
|
976
|
-
idx = ivfl;
|
|
1188
|
+
idx = std::move(ivfl);
|
|
977
1189
|
} else if (h == fourcc("IwFd")) {
|
|
978
|
-
|
|
979
|
-
read_ivf_header(ivfl, f);
|
|
1190
|
+
auto ivfl = std::make_unique<IndexIVFFlatDedup>();
|
|
1191
|
+
read_ivf_header(ivfl.get(), f);
|
|
980
1192
|
ivfl->code_size = ivfl->d * sizeof(float);
|
|
981
1193
|
{
|
|
982
1194
|
std::vector<idx_t> tab;
|
|
983
1195
|
READVECTOR(tab);
|
|
1196
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1197
|
+
tab.size() % 2 == 0,
|
|
1198
|
+
"invalid IVFFlatDedup instances table size: %zd "
|
|
1199
|
+
"(must be even)",
|
|
1200
|
+
tab.size());
|
|
984
1201
|
for (long i = 0; i < tab.size(); i += 2) {
|
|
985
1202
|
std::pair<idx_t, idx_t> pair(tab[i], tab[i + 1]);
|
|
986
1203
|
ivfl->instances.insert(pair);
|
|
987
1204
|
}
|
|
988
1205
|
}
|
|
989
|
-
read_InvertedLists(ivfl, f, io_flags);
|
|
990
|
-
idx = ivfl;
|
|
1206
|
+
read_InvertedLists(*ivfl, f, io_flags);
|
|
1207
|
+
idx = std::move(ivfl);
|
|
991
1208
|
} else if (h == fourcc("IwPn")) {
|
|
992
|
-
|
|
993
|
-
read_ivf_header(ivfp, f);
|
|
1209
|
+
auto ivfp = std::make_unique<IndexIVFFlatPanorama>();
|
|
1210
|
+
read_ivf_header(ivfp.get(), f);
|
|
994
1211
|
ivfp->code_size = ivfp->d * sizeof(float);
|
|
995
1212
|
READ1(ivfp->n_levels);
|
|
996
|
-
read_InvertedLists(ivfp, f, io_flags);
|
|
997
|
-
idx = ivfp;
|
|
1213
|
+
read_InvertedLists(*ivfp, f, io_flags);
|
|
1214
|
+
idx = std::move(ivfp);
|
|
998
1215
|
} else if (h == fourcc("IwFl")) {
|
|
999
|
-
|
|
1000
|
-
read_ivf_header(ivfl, f);
|
|
1216
|
+
auto ivfl = std::make_unique<IndexIVFFlat>();
|
|
1217
|
+
read_ivf_header(ivfl.get(), f);
|
|
1001
1218
|
ivfl->code_size = ivfl->d * sizeof(float);
|
|
1002
|
-
read_InvertedLists(ivfl, f, io_flags);
|
|
1003
|
-
idx = ivfl;
|
|
1219
|
+
read_InvertedLists(*ivfl, f, io_flags);
|
|
1220
|
+
idx = std::move(ivfl);
|
|
1004
1221
|
} else if (h == fourcc("IxSQ")) {
|
|
1005
|
-
|
|
1006
|
-
read_index_header(idxs, f);
|
|
1222
|
+
auto idxs = std::make_unique<IndexScalarQuantizer>();
|
|
1223
|
+
read_index_header(*idxs, f);
|
|
1007
1224
|
read_ScalarQuantizer(&idxs->sq, f);
|
|
1008
1225
|
read_vector(idxs->codes, f);
|
|
1009
1226
|
idxs->code_size = idxs->sq.code_size;
|
|
1010
|
-
idx = idxs;
|
|
1227
|
+
idx = std::move(idxs);
|
|
1011
1228
|
} else if (h == fourcc("IxLa")) {
|
|
1012
1229
|
int d, nsq, scale_nbit, r2;
|
|
1013
1230
|
READ1(d);
|
|
1014
1231
|
READ1(nsq);
|
|
1015
1232
|
READ1(scale_nbit);
|
|
1016
1233
|
READ1(r2);
|
|
1017
|
-
|
|
1018
|
-
|
|
1234
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1235
|
+
nsq > 0, "invalid IndexLattice nsq %d (must be > 0)", nsq);
|
|
1236
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1237
|
+
d > 0 && d % nsq == 0,
|
|
1238
|
+
"invalid IndexLattice d=%d, nsq=%d (d must be > 0 and divisible by nsq)",
|
|
1239
|
+
d,
|
|
1240
|
+
nsq);
|
|
1241
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1242
|
+
r2 > 0, "invalid IndexLattice r2 %d (must be > 0)", r2);
|
|
1243
|
+
int dsq = d / nsq;
|
|
1244
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1245
|
+
dsq >= 2 && (dsq & (dsq - 1)) == 0,
|
|
1246
|
+
"invalid IndexLattice d=%d, nsq=%d: d/nsq=%d must be a power of 2 >= 2",
|
|
1247
|
+
d,
|
|
1248
|
+
nsq,
|
|
1249
|
+
dsq);
|
|
1250
|
+
auto idxl = std::make_unique<IndexLattice>(d, nsq, scale_nbit, r2);
|
|
1251
|
+
read_index_header(*idxl, f);
|
|
1019
1252
|
READVECTOR(idxl->trained);
|
|
1020
|
-
idx = idxl;
|
|
1253
|
+
idx = std::move(idxl);
|
|
1021
1254
|
} else if (h == fourcc("IvSQ")) { // legacy
|
|
1022
|
-
|
|
1255
|
+
auto ivsc = std::make_unique<IndexIVFScalarQuantizer>();
|
|
1023
1256
|
std::vector<std::vector<idx_t>> ids;
|
|
1024
|
-
read_ivf_header(ivsc, f, &ids);
|
|
1257
|
+
read_ivf_header(ivsc.get(), f, &ids);
|
|
1025
1258
|
read_ScalarQuantizer(&ivsc->sq, f);
|
|
1026
1259
|
READ1(ivsc->code_size);
|
|
1027
|
-
ArrayInvertedLists* ail = set_array_invlist(ivsc, ids);
|
|
1260
|
+
ArrayInvertedLists* ail = set_array_invlist(ivsc.get(), ids);
|
|
1028
1261
|
for (int i = 0; i < ivsc->nlist; i++)
|
|
1029
1262
|
READVECTOR(ail->codes[i]);
|
|
1030
|
-
idx = ivsc;
|
|
1263
|
+
idx = std::move(ivsc);
|
|
1031
1264
|
} else if (h == fourcc("IwSQ") || h == fourcc("IwSq")) {
|
|
1032
|
-
|
|
1033
|
-
read_ivf_header(ivsc, f);
|
|
1265
|
+
auto ivsc = std::make_unique<IndexIVFScalarQuantizer>();
|
|
1266
|
+
read_ivf_header(ivsc.get(), f);
|
|
1034
1267
|
read_ScalarQuantizer(&ivsc->sq, f);
|
|
1035
1268
|
READ1(ivsc->code_size);
|
|
1036
1269
|
if (h == fourcc("IwSQ")) {
|
|
@@ -1038,44 +1271,44 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1038
1271
|
} else {
|
|
1039
1272
|
READ1(ivsc->by_residual);
|
|
1040
1273
|
}
|
|
1041
|
-
read_InvertedLists(ivsc, f, io_flags);
|
|
1042
|
-
idx = ivsc;
|
|
1274
|
+
read_InvertedLists(*ivsc, f, io_flags);
|
|
1275
|
+
idx = std::move(ivsc);
|
|
1043
1276
|
} else if (
|
|
1044
1277
|
h == fourcc("IwLS") || h == fourcc("IwRQ") || h == fourcc("IwPL") ||
|
|
1045
1278
|
h == fourcc("IwPR")) {
|
|
1046
1279
|
bool is_LSQ = h == fourcc("IwLS");
|
|
1047
1280
|
bool is_RQ = h == fourcc("IwRQ");
|
|
1048
1281
|
bool is_PLSQ = h == fourcc("IwPL");
|
|
1049
|
-
IndexIVFAdditiveQuantizer
|
|
1282
|
+
std::unique_ptr<IndexIVFAdditiveQuantizer> iva;
|
|
1050
1283
|
if (is_LSQ) {
|
|
1051
|
-
iva =
|
|
1284
|
+
iva = std::make_unique<IndexIVFLocalSearchQuantizer>();
|
|
1052
1285
|
} else if (is_RQ) {
|
|
1053
|
-
iva =
|
|
1286
|
+
iva = std::make_unique<IndexIVFResidualQuantizer>();
|
|
1054
1287
|
} else if (is_PLSQ) {
|
|
1055
|
-
iva =
|
|
1288
|
+
iva = std::make_unique<IndexIVFProductLocalSearchQuantizer>();
|
|
1056
1289
|
} else {
|
|
1057
|
-
iva =
|
|
1290
|
+
iva = std::make_unique<IndexIVFProductResidualQuantizer>();
|
|
1058
1291
|
}
|
|
1059
|
-
read_ivf_header(iva, f);
|
|
1292
|
+
read_ivf_header(iva.get(), f);
|
|
1060
1293
|
READ1(iva->code_size);
|
|
1061
1294
|
if (is_LSQ) {
|
|
1062
|
-
read_LocalSearchQuantizer((LocalSearchQuantizer*)iva->aq, f);
|
|
1295
|
+
read_LocalSearchQuantizer(*(LocalSearchQuantizer*)iva->aq, f);
|
|
1063
1296
|
} else if (is_RQ) {
|
|
1064
|
-
read_ResidualQuantizer((ResidualQuantizer*)iva->aq, f, io_flags);
|
|
1297
|
+
read_ResidualQuantizer(*(ResidualQuantizer*)iva->aq, f, io_flags);
|
|
1065
1298
|
} else if (is_PLSQ) {
|
|
1066
1299
|
read_ProductLocalSearchQuantizer(
|
|
1067
|
-
(ProductLocalSearchQuantizer*)iva->aq, f);
|
|
1300
|
+
*(ProductLocalSearchQuantizer*)iva->aq, f);
|
|
1068
1301
|
} else {
|
|
1069
1302
|
read_ProductResidualQuantizer(
|
|
1070
|
-
(ProductResidualQuantizer*)iva->aq, f, io_flags);
|
|
1303
|
+
*(ProductResidualQuantizer*)iva->aq, f, io_flags);
|
|
1071
1304
|
}
|
|
1072
1305
|
READ1(iva->by_residual);
|
|
1073
1306
|
READ1(iva->use_precomputed_table);
|
|
1074
|
-
read_InvertedLists(iva, f, io_flags);
|
|
1075
|
-
idx = iva;
|
|
1307
|
+
read_InvertedLists(*iva, f, io_flags);
|
|
1308
|
+
idx = std::move(iva);
|
|
1076
1309
|
} else if (h == fourcc("IwSh")) {
|
|
1077
|
-
|
|
1078
|
-
read_ivf_header(ivsp, f);
|
|
1310
|
+
auto ivsp = std::make_unique<IndexIVFSpectralHash>();
|
|
1311
|
+
read_ivf_header(ivsp.get(), f);
|
|
1079
1312
|
ivsp->vt = read_VectorTransform(f);
|
|
1080
1313
|
ivsp->own_fields = true;
|
|
1081
1314
|
READ1(ivsp->nbit);
|
|
@@ -1084,32 +1317,34 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1084
1317
|
READ1(ivsp->period);
|
|
1085
1318
|
READ1(ivsp->threshold_type);
|
|
1086
1319
|
READVECTOR(ivsp->trained);
|
|
1087
|
-
read_InvertedLists(ivsp, f, io_flags);
|
|
1088
|
-
idx = ivsp;
|
|
1320
|
+
read_InvertedLists(*ivsp, f, io_flags);
|
|
1321
|
+
idx = std::move(ivsp);
|
|
1089
1322
|
} else if (
|
|
1090
1323
|
h == fourcc("IvPQ") || h == fourcc("IvQR") || h == fourcc("IwPQ") ||
|
|
1091
1324
|
h == fourcc("IwQR")) {
|
|
1092
1325
|
idx = read_ivfpq(f, h, io_flags);
|
|
1093
1326
|
} else if (h == fourcc("IwIQ")) {
|
|
1094
|
-
auto
|
|
1327
|
+
auto indep = std::make_unique<IndexIVFIndependentQuantizer>();
|
|
1095
1328
|
indep->own_fields = true;
|
|
1096
|
-
read_index_header(indep, f);
|
|
1329
|
+
read_index_header(*indep, f);
|
|
1097
1330
|
indep->quantizer = read_index(f, io_flags);
|
|
1098
1331
|
bool has_vt;
|
|
1099
1332
|
READ1(has_vt);
|
|
1100
1333
|
if (has_vt) {
|
|
1101
1334
|
indep->vt = read_VectorTransform(f);
|
|
1102
1335
|
}
|
|
1103
|
-
|
|
1336
|
+
auto ivf_idx = read_index_up(f, io_flags);
|
|
1337
|
+
indep->index_ivf = dynamic_cast<IndexIVF*>(ivf_idx.get());
|
|
1104
1338
|
FAISS_THROW_IF_NOT(indep->index_ivf);
|
|
1339
|
+
ivf_idx.release();
|
|
1105
1340
|
if (auto index_ivfpq = dynamic_cast<IndexIVFPQ*>(indep->index_ivf)) {
|
|
1106
1341
|
READ1(index_ivfpq->use_precomputed_table);
|
|
1107
1342
|
}
|
|
1108
|
-
idx = indep;
|
|
1343
|
+
idx = std::move(indep);
|
|
1109
1344
|
} else if (h == fourcc("IxPT")) {
|
|
1110
|
-
|
|
1345
|
+
auto ixpt = std::make_unique<IndexPreTransform>();
|
|
1111
1346
|
ixpt->own_fields = true;
|
|
1112
|
-
read_index_header(ixpt, f);
|
|
1347
|
+
read_index_header(*ixpt, f);
|
|
1113
1348
|
int nt;
|
|
1114
1349
|
if (read_old_fmt_hack == 2) {
|
|
1115
1350
|
nt = 1;
|
|
@@ -1120,48 +1355,50 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1120
1355
|
ixpt->chain.push_back(read_VectorTransform(f));
|
|
1121
1356
|
}
|
|
1122
1357
|
ixpt->index = read_index(f, io_flags);
|
|
1123
|
-
idx = ixpt;
|
|
1358
|
+
idx = std::move(ixpt);
|
|
1124
1359
|
} else if (h == fourcc("Imiq")) {
|
|
1125
|
-
|
|
1126
|
-
read_index_header(imiq, f);
|
|
1360
|
+
auto imiq = std::make_unique<MultiIndexQuantizer>();
|
|
1361
|
+
read_index_header(*imiq, f);
|
|
1127
1362
|
read_ProductQuantizer(&imiq->pq, f);
|
|
1128
|
-
idx = imiq;
|
|
1363
|
+
idx = std::move(imiq);
|
|
1129
1364
|
} else if (h == fourcc("IxRF") || h == fourcc("IxRP")) {
|
|
1130
|
-
|
|
1131
|
-
read_index_header(idxrf, f);
|
|
1132
|
-
|
|
1133
|
-
|
|
1365
|
+
auto idxrf = std::make_unique<IndexRefine>();
|
|
1366
|
+
read_index_header(*idxrf, f);
|
|
1367
|
+
auto base = read_index_up(f, io_flags);
|
|
1368
|
+
auto refine = read_index_up(f, io_flags);
|
|
1134
1369
|
READ1(idxrf->k_factor);
|
|
1135
1370
|
if (h == fourcc("IxRP")) {
|
|
1136
1371
|
// then make a RefineFlatPanorama with it
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
} else if (dynamic_cast<IndexFlat*>(idxrf->refine_index)) {
|
|
1372
|
+
auto idxrf_new = std::make_unique<IndexRefinePanorama>();
|
|
1373
|
+
static_cast<IndexRefine&>(*idxrf_new) = *idxrf;
|
|
1374
|
+
idxrf = std::move(idxrf_new);
|
|
1375
|
+
} else if (dynamic_cast<IndexFlat*>(refine.get())) {
|
|
1142
1376
|
// then make a RefineFlat with it
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
delete idxrf_old;
|
|
1377
|
+
auto idxrf_new = std::make_unique<IndexRefineFlat>();
|
|
1378
|
+
static_cast<IndexRefine&>(*idxrf_new) = *idxrf;
|
|
1379
|
+
idxrf = std::move(idxrf_new);
|
|
1147
1380
|
}
|
|
1381
|
+
idxrf->base_index = base.release();
|
|
1382
|
+
idxrf->refine_index = refine.release();
|
|
1148
1383
|
idxrf->own_fields = true;
|
|
1149
1384
|
idxrf->own_refine_index = true;
|
|
1150
|
-
idx = idxrf;
|
|
1385
|
+
idx = std::move(idxrf);
|
|
1151
1386
|
} else if (h == fourcc("IxMp") || h == fourcc("IxM2")) {
|
|
1152
1387
|
bool is_map2 = h == fourcc("IxM2");
|
|
1153
|
-
IndexIDMap
|
|
1154
|
-
|
|
1388
|
+
std::unique_ptr<IndexIDMap> idxmap = is_map2
|
|
1389
|
+
? std::make_unique<IndexIDMap2>()
|
|
1390
|
+
: std::make_unique<IndexIDMap>();
|
|
1391
|
+
read_index_header(*idxmap, f);
|
|
1155
1392
|
idxmap->index = read_index(f, io_flags);
|
|
1156
1393
|
idxmap->own_fields = true;
|
|
1157
1394
|
READVECTOR(idxmap->id_map);
|
|
1158
1395
|
if (is_map2) {
|
|
1159
|
-
static_cast<IndexIDMap2*>(idxmap)->construct_rev_map();
|
|
1396
|
+
static_cast<IndexIDMap2*>(idxmap.get())->construct_rev_map();
|
|
1160
1397
|
}
|
|
1161
|
-
idx = idxmap;
|
|
1398
|
+
idx = std::move(idxmap);
|
|
1162
1399
|
} else if (h == fourcc("Ix2L")) {
|
|
1163
|
-
|
|
1164
|
-
read_index_header(idxp, f);
|
|
1400
|
+
auto idxp = std::make_unique<Index2Layer>();
|
|
1401
|
+
read_index_header(*idxp, f);
|
|
1165
1402
|
idxp->q1.quantizer = read_index(f, io_flags);
|
|
1166
1403
|
READ1(idxp->q1.nlist);
|
|
1167
1404
|
READ1(idxp->q1.quantizer_trains_alone);
|
|
@@ -1170,46 +1407,47 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1170
1407
|
READ1(idxp->code_size_2);
|
|
1171
1408
|
READ1(idxp->code_size);
|
|
1172
1409
|
read_vector(idxp->codes, f);
|
|
1173
|
-
idx = idxp;
|
|
1410
|
+
idx = std::move(idxp);
|
|
1174
1411
|
} else if (
|
|
1175
1412
|
h == fourcc("IHNf") || h == fourcc("IHNp") || h == fourcc("IHNs") ||
|
|
1176
1413
|
h == fourcc("IHN2") || h == fourcc("IHNc") || h == fourcc("IHc2") ||
|
|
1177
1414
|
h == fourcc("IHfP")) {
|
|
1178
|
-
IndexHNSW
|
|
1415
|
+
std::unique_ptr<IndexHNSW> idxhnsw;
|
|
1179
1416
|
if (h == fourcc("IHNf")) {
|
|
1180
|
-
idxhnsw =
|
|
1417
|
+
idxhnsw = std::make_unique<IndexHNSWFlat>();
|
|
1181
1418
|
}
|
|
1182
1419
|
if (h == fourcc("IHfP")) {
|
|
1183
|
-
idxhnsw =
|
|
1420
|
+
idxhnsw = std::make_unique<IndexHNSWFlatPanorama>();
|
|
1184
1421
|
}
|
|
1185
1422
|
if (h == fourcc("IHNp")) {
|
|
1186
|
-
idxhnsw =
|
|
1423
|
+
idxhnsw = std::make_unique<IndexHNSWPQ>();
|
|
1187
1424
|
}
|
|
1188
1425
|
if (h == fourcc("IHNs")) {
|
|
1189
|
-
idxhnsw =
|
|
1426
|
+
idxhnsw = std::make_unique<IndexHNSWSQ>();
|
|
1190
1427
|
}
|
|
1191
1428
|
if (h == fourcc("IHN2")) {
|
|
1192
|
-
idxhnsw =
|
|
1429
|
+
idxhnsw = std::make_unique<IndexHNSW2Level>();
|
|
1193
1430
|
}
|
|
1194
1431
|
if (h == fourcc("IHNc")) {
|
|
1195
|
-
idxhnsw =
|
|
1432
|
+
idxhnsw = std::make_unique<IndexHNSWCagra>();
|
|
1196
1433
|
}
|
|
1197
1434
|
if (h == fourcc("IHc2")) {
|
|
1198
|
-
idxhnsw =
|
|
1435
|
+
idxhnsw = std::make_unique<IndexHNSWCagra>();
|
|
1199
1436
|
}
|
|
1200
|
-
read_index_header(idxhnsw, f);
|
|
1437
|
+
read_index_header(*idxhnsw, f);
|
|
1201
1438
|
if (h == fourcc("IHfP")) {
|
|
1202
|
-
auto idx_panorama =
|
|
1439
|
+
auto idx_panorama =
|
|
1440
|
+
dynamic_cast<IndexHNSWFlatPanorama*>(idxhnsw.get());
|
|
1203
1441
|
size_t nlevels;
|
|
1204
1442
|
READ1(nlevels);
|
|
1205
1443
|
const_cast<size_t&>(idx_panorama->num_panorama_levels) = nlevels;
|
|
1206
|
-
const_cast<
|
|
1207
|
-
(idx_panorama->d
|
|
1444
|
+
const_cast<Panorama&>(idx_panorama->pano) =
|
|
1445
|
+
Panorama(idx_panorama->d * sizeof(float), nlevels, 1);
|
|
1208
1446
|
READVECTOR(idx_panorama->cum_sums);
|
|
1209
1447
|
}
|
|
1210
1448
|
if (h == fourcc("IHNc") || h == fourcc("IHc2")) {
|
|
1211
1449
|
READ1(idxhnsw->keep_max_size_level0);
|
|
1212
|
-
auto idx_hnsw_cagra = dynamic_cast<IndexHNSWCagra*>(idxhnsw);
|
|
1450
|
+
auto idx_hnsw_cagra = dynamic_cast<IndexHNSWCagra*>(idxhnsw.get());
|
|
1213
1451
|
READ1(idx_hnsw_cagra->base_level_only);
|
|
1214
1452
|
READ1(idx_hnsw_cagra->num_base_level_search_entrypoints);
|
|
1215
1453
|
if (h == fourcc("IHc2")) {
|
|
@@ -1218,47 +1456,47 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1218
1456
|
idx_hnsw_cagra->set_numeric_type(faiss::Float32);
|
|
1219
1457
|
}
|
|
1220
1458
|
}
|
|
1221
|
-
read_HNSW(
|
|
1459
|
+
read_HNSW(idxhnsw->hnsw, f);
|
|
1222
1460
|
idxhnsw->hnsw.is_panorama = (h == fourcc("IHfP"));
|
|
1223
1461
|
idxhnsw->storage = read_index(f, io_flags);
|
|
1224
1462
|
idxhnsw->own_fields = idxhnsw->storage != nullptr;
|
|
1225
1463
|
if (h == fourcc("IHNp") && !(io_flags & IO_FLAG_PQ_SKIP_SDC_TABLE)) {
|
|
1226
1464
|
dynamic_cast<IndexPQ*>(idxhnsw->storage)->pq.compute_sdc_table();
|
|
1227
1465
|
}
|
|
1228
|
-
idx = idxhnsw;
|
|
1466
|
+
idx = std::move(idxhnsw);
|
|
1229
1467
|
} else if (
|
|
1230
1468
|
h == fourcc("INSf") || h == fourcc("INSp") || h == fourcc("INSs")) {
|
|
1231
|
-
IndexNSG
|
|
1469
|
+
std::unique_ptr<IndexNSG> idxnsg;
|
|
1232
1470
|
if (h == fourcc("INSf")) {
|
|
1233
|
-
idxnsg =
|
|
1471
|
+
idxnsg = std::make_unique<IndexNSGFlat>();
|
|
1234
1472
|
}
|
|
1235
1473
|
if (h == fourcc("INSp")) {
|
|
1236
|
-
idxnsg =
|
|
1474
|
+
idxnsg = std::make_unique<IndexNSGPQ>();
|
|
1237
1475
|
}
|
|
1238
1476
|
if (h == fourcc("INSs")) {
|
|
1239
|
-
idxnsg =
|
|
1477
|
+
idxnsg = std::make_unique<IndexNSGSQ>();
|
|
1240
1478
|
}
|
|
1241
|
-
read_index_header(idxnsg, f);
|
|
1479
|
+
read_index_header(*idxnsg, f);
|
|
1242
1480
|
READ1(idxnsg->GK);
|
|
1243
1481
|
READ1(idxnsg->build_type);
|
|
1244
1482
|
READ1(idxnsg->nndescent_S);
|
|
1245
1483
|
READ1(idxnsg->nndescent_R);
|
|
1246
1484
|
READ1(idxnsg->nndescent_L);
|
|
1247
1485
|
READ1(idxnsg->nndescent_iter);
|
|
1248
|
-
read_NSG(
|
|
1486
|
+
read_NSG(idxnsg->nsg, f);
|
|
1249
1487
|
idxnsg->storage = read_index(f, io_flags);
|
|
1250
1488
|
idxnsg->own_fields = true;
|
|
1251
|
-
idx = idxnsg;
|
|
1489
|
+
idx = std::move(idxnsg);
|
|
1252
1490
|
} else if (h == fourcc("INNf")) {
|
|
1253
|
-
|
|
1254
|
-
read_index_header(idxnnd, f);
|
|
1255
|
-
read_NNDescent(
|
|
1491
|
+
auto idxnnd = std::make_unique<IndexNNDescentFlat>();
|
|
1492
|
+
read_index_header(*idxnnd, f);
|
|
1493
|
+
read_NNDescent(idxnnd->nndescent, f);
|
|
1256
1494
|
idxnnd->storage = read_index(f, io_flags);
|
|
1257
1495
|
idxnnd->own_fields = true;
|
|
1258
|
-
idx = idxnnd;
|
|
1496
|
+
idx = std::move(idxnnd);
|
|
1259
1497
|
} else if (h == fourcc("IPfs")) {
|
|
1260
|
-
|
|
1261
|
-
read_index_header(idxpqfs, f);
|
|
1498
|
+
auto idxpqfs = std::make_unique<IndexPQFastScan>();
|
|
1499
|
+
read_index_header(*idxpqfs, f);
|
|
1262
1500
|
read_ProductQuantizer(&idxpqfs->pq, f);
|
|
1263
1501
|
READ1(idxpqfs->implem);
|
|
1264
1502
|
READ1(idxpqfs->bbs);
|
|
@@ -1273,11 +1511,11 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1273
1511
|
idxpqfs->ksub = (1 << pq.nbits);
|
|
1274
1512
|
idxpqfs->code_size = pq.code_size;
|
|
1275
1513
|
|
|
1276
|
-
idx = idxpqfs;
|
|
1514
|
+
idx = std::move(idxpqfs);
|
|
1277
1515
|
|
|
1278
1516
|
} else if (h == fourcc("IwPf")) {
|
|
1279
|
-
|
|
1280
|
-
read_ivf_header(ivpq, f);
|
|
1517
|
+
auto ivpq = std::make_unique<IndexIVFPQFastScan>();
|
|
1518
|
+
read_ivf_header(ivpq.get(), f);
|
|
1281
1519
|
READ1(ivpq->by_residual);
|
|
1282
1520
|
READ1(ivpq->code_size);
|
|
1283
1521
|
READ1(ivpq->bbs);
|
|
@@ -1285,7 +1523,7 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1285
1523
|
READ1(ivpq->implem);
|
|
1286
1524
|
READ1(ivpq->qbs2);
|
|
1287
1525
|
read_ProductQuantizer(&ivpq->pq, f);
|
|
1288
|
-
read_InvertedLists(ivpq, f, io_flags);
|
|
1526
|
+
read_InvertedLists(*ivpq, f, io_flags);
|
|
1289
1527
|
ivpq->precompute_table();
|
|
1290
1528
|
|
|
1291
1529
|
const auto& pq = ivpq->pq;
|
|
@@ -1295,30 +1533,38 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1295
1533
|
ivpq->code_size = pq.code_size;
|
|
1296
1534
|
ivpq->init_code_packer();
|
|
1297
1535
|
|
|
1298
|
-
idx = ivpq;
|
|
1536
|
+
idx = std::move(ivpq);
|
|
1299
1537
|
} else if (h == fourcc("IRMf")) {
|
|
1300
|
-
|
|
1301
|
-
read_index_header(imm, f);
|
|
1538
|
+
auto imm = std::make_unique<IndexRowwiseMinMax>();
|
|
1539
|
+
read_index_header(*imm, f);
|
|
1302
1540
|
|
|
1303
1541
|
imm->index = read_index(f, io_flags);
|
|
1304
1542
|
imm->own_fields = true;
|
|
1305
1543
|
|
|
1306
|
-
idx = imm;
|
|
1544
|
+
idx = std::move(imm);
|
|
1307
1545
|
} else if (h == fourcc("IRMh")) {
|
|
1308
|
-
|
|
1309
|
-
read_index_header(imm, f);
|
|
1546
|
+
auto imm = std::make_unique<IndexRowwiseMinMaxFP16>();
|
|
1547
|
+
read_index_header(*imm, f);
|
|
1310
1548
|
|
|
1311
1549
|
imm->index = read_index(f, io_flags);
|
|
1312
1550
|
imm->own_fields = true;
|
|
1313
1551
|
|
|
1314
|
-
idx = imm;
|
|
1315
|
-
} else if (h == fourcc("Irfs")) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1552
|
+
idx = std::move(imm);
|
|
1553
|
+
} else if (h == fourcc("Irfn") || h == fourcc("Irfs")) {
|
|
1554
|
+
// Irfn = new format (aux data embedded in SIMD blocks)
|
|
1555
|
+
// Irfs = legacy format (flat_storage separate, needs migration)
|
|
1556
|
+
const bool is_legacy = (h == fourcc("Irfs"));
|
|
1557
|
+
|
|
1558
|
+
auto idxqfs = std::make_unique<IndexRaBitQFastScan>();
|
|
1559
|
+
read_index_header(*idxqfs, f);
|
|
1560
|
+
read_RaBitQuantizer(idxqfs->rabitq, f, true);
|
|
1319
1561
|
READVECTOR(idxqfs->center);
|
|
1320
1562
|
READ1(idxqfs->qb);
|
|
1321
|
-
|
|
1563
|
+
|
|
1564
|
+
std::vector<uint8_t> legacy_flat_storage;
|
|
1565
|
+
if (is_legacy) {
|
|
1566
|
+
READVECTOR(legacy_flat_storage);
|
|
1567
|
+
}
|
|
1322
1568
|
|
|
1323
1569
|
READ1(idxqfs->bbs);
|
|
1324
1570
|
READ1(idxqfs->ntotal2);
|
|
@@ -1332,33 +1578,55 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1332
1578
|
idxqfs->ksub = (1 << nbits_fastscan);
|
|
1333
1579
|
|
|
1334
1580
|
READVECTOR(idxqfs->codes);
|
|
1335
|
-
|
|
1581
|
+
|
|
1582
|
+
if (is_legacy) {
|
|
1583
|
+
const size_t storage_size =
|
|
1584
|
+
rabitq_utils::compute_per_vector_storage_size(
|
|
1585
|
+
idxqfs->rabitq.nb_bits, idxqfs->d);
|
|
1586
|
+
|
|
1587
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
1588
|
+
legacy_flat_storage.size() ==
|
|
1589
|
+
static_cast<size_t>(idxqfs->ntotal) * storage_size,
|
|
1590
|
+
"legacy flat_storage size mismatch during migration");
|
|
1591
|
+
|
|
1592
|
+
rabitq_utils::populate_block_aux_from_flat_storage(
|
|
1593
|
+
legacy_flat_storage,
|
|
1594
|
+
idxqfs->codes,
|
|
1595
|
+
static_cast<size_t>(idxqfs->ntotal),
|
|
1596
|
+
idxqfs->bbs,
|
|
1597
|
+
idxqfs->M2,
|
|
1598
|
+
((idxqfs->M2 + 1) / 2) * idxqfs->bbs,
|
|
1599
|
+
idxqfs->get_block_stride(),
|
|
1600
|
+
storage_size);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
idx = std::move(idxqfs);
|
|
1336
1604
|
} else if (h == fourcc("Ixrq")) {
|
|
1337
|
-
|
|
1338
|
-
read_index_header(idxq, f);
|
|
1339
|
-
read_RaBitQuantizer(
|
|
1605
|
+
auto idxq = std::make_unique<IndexRaBitQ>();
|
|
1606
|
+
read_index_header(*idxq, f);
|
|
1607
|
+
read_RaBitQuantizer(idxq->rabitq, f, false);
|
|
1340
1608
|
READVECTOR(idxq->codes);
|
|
1341
1609
|
READVECTOR(idxq->center);
|
|
1342
1610
|
READ1(idxq->qb);
|
|
1343
1611
|
|
|
1344
1612
|
// rabitq.nb_bits is already set to 1 by read_RaBitQuantizer
|
|
1345
1613
|
idxq->code_size = idxq->rabitq.code_size;
|
|
1346
|
-
idx = idxq;
|
|
1614
|
+
idx = std::move(idxq);
|
|
1347
1615
|
} else if (h == fourcc("Ixrr")) {
|
|
1348
1616
|
// Ixrr = multi-bit format (new)
|
|
1349
|
-
|
|
1350
|
-
read_index_header(idxq, f);
|
|
1351
|
-
read_RaBitQuantizer(
|
|
1617
|
+
auto idxq = std::make_unique<IndexRaBitQ>();
|
|
1618
|
+
read_index_header(*idxq, f);
|
|
1619
|
+
read_RaBitQuantizer(idxq->rabitq, f, true); // Reads nb_bits from file
|
|
1352
1620
|
READVECTOR(idxq->codes);
|
|
1353
1621
|
READVECTOR(idxq->center);
|
|
1354
1622
|
READ1(idxq->qb);
|
|
1355
1623
|
|
|
1356
1624
|
idxq->code_size = idxq->rabitq.code_size;
|
|
1357
|
-
idx = idxq;
|
|
1625
|
+
idx = std::move(idxq);
|
|
1358
1626
|
} else if (h == fourcc("Iwrq")) {
|
|
1359
|
-
|
|
1360
|
-
read_ivf_header(ivrq, f);
|
|
1361
|
-
read_RaBitQuantizer(
|
|
1627
|
+
auto ivrq = std::make_unique<IndexIVFRaBitQ>();
|
|
1628
|
+
read_ivf_header(ivrq.get(), f);
|
|
1629
|
+
read_RaBitQuantizer(ivrq->rabitq, f, false);
|
|
1362
1630
|
READ1(ivrq->code_size);
|
|
1363
1631
|
READ1(ivrq->by_residual);
|
|
1364
1632
|
READ1(ivrq->qb);
|
|
@@ -1368,13 +1636,13 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1368
1636
|
ivrq->rabitq.code_size =
|
|
1369
1637
|
ivrq->rabitq.compute_code_size(ivrq->d, ivrq->rabitq.nb_bits);
|
|
1370
1638
|
ivrq->code_size = ivrq->rabitq.code_size;
|
|
1371
|
-
read_InvertedLists(ivrq, f, io_flags);
|
|
1372
|
-
idx = ivrq;
|
|
1639
|
+
read_InvertedLists(*ivrq, f, io_flags);
|
|
1640
|
+
idx = std::move(ivrq);
|
|
1373
1641
|
} else if (h == fourcc("Iwrr")) {
|
|
1374
1642
|
// Iwrr = multi-bit format (new)
|
|
1375
|
-
|
|
1376
|
-
read_ivf_header(ivrq, f);
|
|
1377
|
-
read_RaBitQuantizer(
|
|
1643
|
+
auto ivrq = std::make_unique<IndexIVFRaBitQ>();
|
|
1644
|
+
read_ivf_header(ivrq.get(), f);
|
|
1645
|
+
read_RaBitQuantizer(ivrq->rabitq, f, true); // Reads nb_bits from file
|
|
1378
1646
|
READ1(ivrq->code_size);
|
|
1379
1647
|
READ1(ivrq->by_residual);
|
|
1380
1648
|
READ1(ivrq->qb);
|
|
@@ -1383,22 +1651,22 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1383
1651
|
ivrq->rabitq.code_size =
|
|
1384
1652
|
ivrq->rabitq.compute_code_size(ivrq->d, ivrq->rabitq.nb_bits);
|
|
1385
1653
|
ivrq->code_size = ivrq->rabitq.code_size;
|
|
1386
|
-
read_InvertedLists(ivrq, f, io_flags);
|
|
1387
|
-
idx = ivrq;
|
|
1654
|
+
read_InvertedLists(*ivrq, f, io_flags);
|
|
1655
|
+
idx = std::move(ivrq);
|
|
1388
1656
|
}
|
|
1389
1657
|
#ifdef FAISS_ENABLE_SVS
|
|
1390
1658
|
else if (
|
|
1391
1659
|
h == fourcc("ILVQ") || h == fourcc("ISVL") || h == fourcc("ISVD")) {
|
|
1392
|
-
IndexSVSVamana
|
|
1660
|
+
std::unique_ptr<IndexSVSVamana> svs;
|
|
1393
1661
|
if (h == fourcc("ILVQ")) {
|
|
1394
|
-
svs =
|
|
1662
|
+
svs = std::make_unique<IndexSVSVamanaLVQ>();
|
|
1395
1663
|
} else if (h == fourcc("ISVL")) {
|
|
1396
|
-
svs =
|
|
1664
|
+
svs = std::make_unique<IndexSVSVamanaLeanVec>();
|
|
1397
1665
|
} else if (h == fourcc("ISVD")) {
|
|
1398
|
-
svs =
|
|
1666
|
+
svs = std::make_unique<IndexSVSVamana>();
|
|
1399
1667
|
}
|
|
1400
1668
|
|
|
1401
|
-
read_index_header(svs, f);
|
|
1669
|
+
read_index_header(*svs, f);
|
|
1402
1670
|
READ1(svs->graph_max_degree);
|
|
1403
1671
|
READ1(svs->alpha);
|
|
1404
1672
|
READ1(svs->search_window_size);
|
|
@@ -1409,7 +1677,7 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1409
1677
|
READ1(svs->use_full_search_history);
|
|
1410
1678
|
READ1(svs->storage_kind);
|
|
1411
1679
|
if (h == fourcc("ISVL")) {
|
|
1412
|
-
READ1(dynamic_cast<IndexSVSVamanaLeanVec*>(svs)->leanvec_d);
|
|
1680
|
+
READ1(dynamic_cast<IndexSVSVamanaLeanVec*>(svs.get())->leanvec_d);
|
|
1413
1681
|
}
|
|
1414
1682
|
|
|
1415
1683
|
bool initialized;
|
|
@@ -1425,14 +1693,14 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1425
1693
|
if (trained) {
|
|
1426
1694
|
faiss::svs_io::ReaderStreambuf rbuf(f);
|
|
1427
1695
|
std::istream is(&rbuf);
|
|
1428
|
-
dynamic_cast<IndexSVSVamanaLeanVec*>(svs)
|
|
1696
|
+
dynamic_cast<IndexSVSVamanaLeanVec*>(svs.get())
|
|
1429
1697
|
->deserialize_training_data(is);
|
|
1430
1698
|
}
|
|
1431
1699
|
}
|
|
1432
|
-
idx = svs;
|
|
1700
|
+
idx = std::move(svs);
|
|
1433
1701
|
} else if (h == fourcc("ISVF")) {
|
|
1434
|
-
|
|
1435
|
-
read_index_header(svs, f);
|
|
1702
|
+
auto svs = std::make_unique<IndexSVSFlat>();
|
|
1703
|
+
read_index_header(*svs, f);
|
|
1436
1704
|
|
|
1437
1705
|
bool initialized;
|
|
1438
1706
|
READ1(initialized);
|
|
@@ -1440,14 +1708,18 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1440
1708
|
faiss::svs_io::ReaderStreambuf rbuf(f);
|
|
1441
1709
|
std::istream is(&rbuf);
|
|
1442
1710
|
svs->deserialize_impl(is);
|
|
1443
|
-
idx = svs;
|
|
1444
1711
|
}
|
|
1712
|
+
idx = std::move(svs);
|
|
1445
1713
|
}
|
|
1446
1714
|
#endif // FAISS_ENABLE_SVS
|
|
1447
|
-
else if (h == fourcc("Iwrf")) {
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1715
|
+
else if (h == fourcc("Iwrn") || h == fourcc("Iwrf")) {
|
|
1716
|
+
// Iwrn = new format (aux data embedded in SIMD blocks)
|
|
1717
|
+
// Iwrf = legacy format (flat_storage separate, needs migration)
|
|
1718
|
+
const bool is_legacy = (h == fourcc("Iwrf"));
|
|
1719
|
+
|
|
1720
|
+
auto ivrqfs = std::make_unique<IndexIVFRaBitQFastScan>();
|
|
1721
|
+
read_ivf_header(ivrqfs.get(), f);
|
|
1722
|
+
read_RaBitQuantizer(ivrqfs->rabitq, f);
|
|
1451
1723
|
READ1(ivrqfs->by_residual);
|
|
1452
1724
|
READ1(ivrqfs->code_size);
|
|
1453
1725
|
READ1(ivrqfs->bbs);
|
|
@@ -1456,7 +1728,11 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1456
1728
|
READ1(ivrqfs->implem);
|
|
1457
1729
|
READ1(ivrqfs->qb);
|
|
1458
1730
|
READ1(ivrqfs->centered);
|
|
1459
|
-
|
|
1731
|
+
|
|
1732
|
+
std::vector<uint8_t> legacy_flat_storage;
|
|
1733
|
+
if (is_legacy) {
|
|
1734
|
+
READVECTOR(legacy_flat_storage);
|
|
1735
|
+
}
|
|
1460
1736
|
|
|
1461
1737
|
// Initialize FastScan base class fields
|
|
1462
1738
|
const size_t M_fastscan = (ivrqfs->d + 3) / 4;
|
|
@@ -1465,87 +1741,140 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1465
1741
|
ivrqfs->nbits = nbits_fastscan;
|
|
1466
1742
|
ivrqfs->ksub = (1 << nbits_fastscan);
|
|
1467
1743
|
|
|
1468
|
-
read_InvertedLists(ivrqfs, f, io_flags);
|
|
1744
|
+
read_InvertedLists(*ivrqfs, f, io_flags);
|
|
1469
1745
|
ivrqfs->init_code_packer();
|
|
1470
|
-
|
|
1746
|
+
|
|
1747
|
+
if (is_legacy) {
|
|
1748
|
+
auto* bil = dynamic_cast<BlockInvertedLists*>(ivrqfs->invlists);
|
|
1749
|
+
FAISS_THROW_IF_NOT(bil);
|
|
1750
|
+
|
|
1751
|
+
const size_t storage_size =
|
|
1752
|
+
rabitq_utils::compute_per_vector_storage_size(
|
|
1753
|
+
ivrqfs->rabitq.nb_bits, ivrqfs->d);
|
|
1754
|
+
const size_t new_block_stride = ivrqfs->get_block_stride();
|
|
1755
|
+
|
|
1756
|
+
for (size_t list_no = 0; list_no < ivrqfs->nlist; list_no++) {
|
|
1757
|
+
if (bil->list_size(list_no) == 0) {
|
|
1758
|
+
continue;
|
|
1759
|
+
}
|
|
1760
|
+
rabitq_utils::populate_block_aux_from_flat_storage(
|
|
1761
|
+
legacy_flat_storage,
|
|
1762
|
+
bil->codes[list_no],
|
|
1763
|
+
bil->list_size(list_no),
|
|
1764
|
+
ivrqfs->bbs,
|
|
1765
|
+
ivrqfs->M2,
|
|
1766
|
+
bil->block_size,
|
|
1767
|
+
new_block_stride,
|
|
1768
|
+
storage_size,
|
|
1769
|
+
bil->ids[list_no].data());
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
if (bil->block_size < new_block_stride) {
|
|
1773
|
+
bil->block_size = new_block_stride;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
idx = std::move(ivrqfs);
|
|
1471
1778
|
} else {
|
|
1472
1779
|
FAISS_THROW_FMT(
|
|
1473
1780
|
"Index type 0x%08x (\"%s\") not recognized",
|
|
1474
1781
|
h,
|
|
1475
1782
|
fourcc_inv_printable(h).c_str());
|
|
1476
|
-
idx
|
|
1783
|
+
idx.reset();
|
|
1477
1784
|
}
|
|
1478
1785
|
return idx;
|
|
1479
1786
|
}
|
|
1480
1787
|
|
|
1481
|
-
Index* read_index(
|
|
1788
|
+
Index* read_index(IOReader* f, int io_flags) {
|
|
1789
|
+
return read_index_up(f, io_flags).release();
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
std::unique_ptr<Index> read_index_up(FILE* f, int io_flags) {
|
|
1482
1793
|
if ((io_flags & IO_FLAG_MMAP_IFC) == IO_FLAG_MMAP_IFC) {
|
|
1483
1794
|
// enable mmap-supporting IOReader
|
|
1484
1795
|
auto owner = std::make_shared<MmappedFileMappingOwner>(f);
|
|
1485
1796
|
MappedFileIOReader reader(owner);
|
|
1486
|
-
return
|
|
1797
|
+
return read_index_up(&reader, io_flags);
|
|
1487
1798
|
} else {
|
|
1488
1799
|
FileIOReader reader(f);
|
|
1489
|
-
return
|
|
1800
|
+
return read_index_up(&reader, io_flags);
|
|
1490
1801
|
}
|
|
1491
1802
|
}
|
|
1492
1803
|
|
|
1493
|
-
Index* read_index(
|
|
1804
|
+
Index* read_index(FILE* f, int io_flags) {
|
|
1805
|
+
return read_index_up(f, io_flags).release();
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
std::unique_ptr<Index> read_index_up(const char* fname, int io_flags) {
|
|
1494
1809
|
if ((io_flags & IO_FLAG_MMAP_IFC) == IO_FLAG_MMAP_IFC) {
|
|
1495
1810
|
// enable mmap-supporting IOReader
|
|
1496
1811
|
auto owner = std::make_shared<MmappedFileMappingOwner>(fname);
|
|
1497
1812
|
MappedFileIOReader reader(owner);
|
|
1498
|
-
return
|
|
1813
|
+
return read_index_up(&reader, io_flags);
|
|
1499
1814
|
} else {
|
|
1500
1815
|
FileIOReader reader(fname);
|
|
1501
|
-
|
|
1502
|
-
return idx;
|
|
1816
|
+
return read_index_up(&reader, io_flags);
|
|
1503
1817
|
}
|
|
1504
1818
|
}
|
|
1505
1819
|
|
|
1506
|
-
|
|
1820
|
+
Index* read_index(const char* fname, int io_flags) {
|
|
1821
|
+
return read_index_up(fname, io_flags).release();
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
std::unique_ptr<VectorTransform> read_VectorTransform_up(const char* fname) {
|
|
1507
1825
|
FileIOReader reader(fname);
|
|
1508
|
-
|
|
1509
|
-
|
|
1826
|
+
return read_VectorTransform_up(&reader);
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
VectorTransform* read_VectorTransform(const char* fname) {
|
|
1830
|
+
return read_VectorTransform_up(fname).release();
|
|
1510
1831
|
}
|
|
1511
1832
|
|
|
1512
1833
|
/*************************************************************
|
|
1513
1834
|
* Read binary indexes
|
|
1514
1835
|
**************************************************************/
|
|
1515
1836
|
|
|
1516
|
-
static void read_InvertedLists(IndexBinaryIVF
|
|
1517
|
-
|
|
1837
|
+
static void read_InvertedLists(IndexBinaryIVF& ivf, IOReader* f, int io_flags) {
|
|
1838
|
+
auto ils = read_InvertedLists_up(f, io_flags);
|
|
1518
1839
|
FAISS_THROW_IF_NOT(
|
|
1519
1840
|
!ils ||
|
|
1520
|
-
(ils->nlist == ivf
|
|
1521
|
-
ivf
|
|
1522
|
-
ivf
|
|
1841
|
+
(ils->nlist == ivf.nlist && ils->code_size == ivf.code_size));
|
|
1842
|
+
ivf.invlists = ils.release();
|
|
1843
|
+
ivf.own_invlists = true;
|
|
1523
1844
|
}
|
|
1524
1845
|
|
|
1525
|
-
static void read_index_binary_header(IndexBinary
|
|
1526
|
-
READ1(idx
|
|
1527
|
-
READ1(idx
|
|
1528
|
-
READ1(idx
|
|
1529
|
-
READ1(idx
|
|
1530
|
-
|
|
1531
|
-
|
|
1846
|
+
static void read_index_binary_header(IndexBinary& idx, IOReader* f) {
|
|
1847
|
+
READ1(idx.d);
|
|
1848
|
+
READ1(idx.code_size);
|
|
1849
|
+
READ1(idx.ntotal);
|
|
1850
|
+
READ1(idx.is_trained);
|
|
1851
|
+
int metric_type_int;
|
|
1852
|
+
READ1(metric_type_int);
|
|
1853
|
+
idx.metric_type = metric_type_from_int(metric_type_int);
|
|
1854
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1855
|
+
idx.d >= 0, "invalid binary index dimension %d", idx.d);
|
|
1856
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1857
|
+
idx.ntotal >= 0,
|
|
1858
|
+
"invalid binary index ntotal %" PRId64,
|
|
1859
|
+
(int64_t)idx.ntotal);
|
|
1860
|
+
idx.verbose = false;
|
|
1532
1861
|
}
|
|
1533
1862
|
|
|
1534
1863
|
static void read_binary_ivf_header(
|
|
1535
|
-
IndexBinaryIVF
|
|
1864
|
+
IndexBinaryIVF& ivf,
|
|
1536
1865
|
IOReader* f,
|
|
1537
1866
|
std::vector<std::vector<idx_t>>* ids = nullptr) {
|
|
1538
1867
|
read_index_binary_header(ivf, f);
|
|
1539
|
-
READ1(ivf
|
|
1540
|
-
READ1(ivf
|
|
1541
|
-
ivf
|
|
1542
|
-
ivf
|
|
1868
|
+
READ1(ivf.nlist);
|
|
1869
|
+
READ1(ivf.nprobe);
|
|
1870
|
+
ivf.quantizer = read_index_binary(f);
|
|
1871
|
+
ivf.own_fields = true;
|
|
1543
1872
|
if (ids) { // used in legacy "Iv" formats
|
|
1544
|
-
ids->resize(ivf
|
|
1545
|
-
for (size_t i = 0; i < ivf
|
|
1873
|
+
ids->resize(ivf.nlist);
|
|
1874
|
+
for (size_t i = 0; i < ivf.nlist; i++)
|
|
1546
1875
|
READVECTOR((*ids)[i]);
|
|
1547
1876
|
}
|
|
1548
|
-
read_direct_map(&ivf
|
|
1877
|
+
read_direct_map(&ivf.direct_map, f);
|
|
1549
1878
|
}
|
|
1550
1879
|
|
|
1551
1880
|
static void read_binary_hash_invlists(
|
|
@@ -1557,8 +1886,20 @@ static void read_binary_hash_invlists(
|
|
|
1557
1886
|
int il_nbit = 0;
|
|
1558
1887
|
READ1(il_nbit);
|
|
1559
1888
|
// buffer for bitstrings
|
|
1560
|
-
|
|
1889
|
+
size_t bits_per_entry = (size_t)b + (size_t)il_nbit;
|
|
1890
|
+
size_t total_bits =
|
|
1891
|
+
mul_no_overflow(bits_per_entry, sz, "binary hash invlists");
|
|
1892
|
+
size_t needed_bytes = (total_bits + 7) / 8;
|
|
1893
|
+
std::vector<uint8_t> buf;
|
|
1561
1894
|
READVECTOR(buf);
|
|
1895
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1896
|
+
buf.size() >= needed_bytes,
|
|
1897
|
+
"binary hash invlists: buffer size %zd < needed %zd bytes "
|
|
1898
|
+
"for %zd entries of %zd bits each",
|
|
1899
|
+
buf.size(),
|
|
1900
|
+
needed_bytes,
|
|
1901
|
+
sz,
|
|
1902
|
+
bits_per_entry);
|
|
1562
1903
|
BitstringReader rd(buf.data(), buf.size());
|
|
1563
1904
|
invlists.reserve(sz);
|
|
1564
1905
|
for (size_t i = 0; i < sz; i++) {
|
|
@@ -1582,7 +1923,10 @@ static void read_binary_multi_hash_map(
|
|
|
1582
1923
|
READ1(sz);
|
|
1583
1924
|
std::vector<uint8_t> buf;
|
|
1584
1925
|
READVECTOR(buf);
|
|
1585
|
-
size_t nbit = (
|
|
1926
|
+
size_t nbit = add_no_overflow(
|
|
1927
|
+
mul_no_overflow((size_t)(b + id_bits), sz, "multi hash map"),
|
|
1928
|
+
mul_no_overflow(ntotal, (size_t)id_bits, "multi hash map"),
|
|
1929
|
+
"multi hash map total bits");
|
|
1586
1930
|
FAISS_THROW_IF_NOT(buf.size() == (nbit + 7) / 8);
|
|
1587
1931
|
BitstringReader rd(buf.data(), buf.size());
|
|
1588
1932
|
map.reserve(sz);
|
|
@@ -1596,72 +1940,74 @@ static void read_binary_multi_hash_map(
|
|
|
1596
1940
|
}
|
|
1597
1941
|
}
|
|
1598
1942
|
|
|
1599
|
-
IndexBinary
|
|
1600
|
-
IndexBinary
|
|
1943
|
+
std::unique_ptr<IndexBinary> read_index_binary_up(IOReader* f, int io_flags) {
|
|
1944
|
+
std::unique_ptr<IndexBinary> idx;
|
|
1601
1945
|
uint32_t h;
|
|
1602
1946
|
READ1(h);
|
|
1603
1947
|
if (h == fourcc("IBxF")) {
|
|
1604
|
-
|
|
1605
|
-
read_index_binary_header(idxf, f);
|
|
1948
|
+
auto idxf = std::make_unique<IndexBinaryFlat>();
|
|
1949
|
+
read_index_binary_header(*idxf, f);
|
|
1606
1950
|
read_vector(idxf->xb, f);
|
|
1607
1951
|
FAISS_THROW_IF_NOT(idxf->xb.size() == idxf->ntotal * idxf->code_size);
|
|
1608
|
-
|
|
1609
|
-
idx = idxf;
|
|
1952
|
+
idx = std::move(idxf);
|
|
1610
1953
|
} else if (h == fourcc("IBwF")) {
|
|
1611
|
-
|
|
1612
|
-
read_binary_ivf_header(ivf, f);
|
|
1613
|
-
read_InvertedLists(ivf, f, io_flags);
|
|
1614
|
-
idx = ivf;
|
|
1954
|
+
auto ivf = std::make_unique<IndexBinaryIVF>();
|
|
1955
|
+
read_binary_ivf_header(*ivf, f);
|
|
1956
|
+
read_InvertedLists(*ivf, f, io_flags);
|
|
1957
|
+
idx = std::move(ivf);
|
|
1615
1958
|
} else if (h == fourcc("IBFf")) {
|
|
1616
|
-
|
|
1617
|
-
read_index_binary_header(idxff, f);
|
|
1959
|
+
auto idxff = std::make_unique<IndexBinaryFromFloat>();
|
|
1960
|
+
read_index_binary_header(*idxff, f);
|
|
1618
1961
|
idxff->own_fields = true;
|
|
1619
1962
|
idxff->index = read_index(f, io_flags);
|
|
1620
|
-
idx = idxff;
|
|
1963
|
+
idx = std::move(idxff);
|
|
1621
1964
|
} else if (h == fourcc("IBHf")) {
|
|
1622
|
-
|
|
1623
|
-
read_index_binary_header(idxhnsw, f);
|
|
1624
|
-
read_HNSW(
|
|
1965
|
+
auto idxhnsw = std::make_unique<IndexBinaryHNSW>();
|
|
1966
|
+
read_index_binary_header(*idxhnsw, f);
|
|
1967
|
+
read_HNSW(idxhnsw->hnsw, f);
|
|
1625
1968
|
idxhnsw->hnsw.is_panorama = false;
|
|
1626
1969
|
idxhnsw->storage = read_index_binary(f, io_flags);
|
|
1627
1970
|
idxhnsw->own_fields = true;
|
|
1628
|
-
idx = idxhnsw;
|
|
1971
|
+
idx = std::move(idxhnsw);
|
|
1629
1972
|
} else if (h == fourcc("IBHc")) {
|
|
1630
|
-
|
|
1631
|
-
read_index_binary_header(idxhnsw, f);
|
|
1973
|
+
auto idxhnsw = std::make_unique<IndexBinaryHNSWCagra>();
|
|
1974
|
+
read_index_binary_header(*idxhnsw, f);
|
|
1632
1975
|
READ1(idxhnsw->keep_max_size_level0);
|
|
1633
1976
|
READ1(idxhnsw->base_level_only);
|
|
1634
1977
|
READ1(idxhnsw->num_base_level_search_entrypoints);
|
|
1635
|
-
read_HNSW(
|
|
1978
|
+
read_HNSW(idxhnsw->hnsw, f);
|
|
1636
1979
|
idxhnsw->hnsw.is_panorama = false;
|
|
1637
1980
|
idxhnsw->storage = read_index_binary(f, io_flags);
|
|
1638
1981
|
idxhnsw->own_fields = true;
|
|
1639
|
-
idx = idxhnsw;
|
|
1982
|
+
idx = std::move(idxhnsw);
|
|
1640
1983
|
} else if (h == fourcc("IBMp") || h == fourcc("IBM2")) {
|
|
1641
1984
|
bool is_map2 = h == fourcc("IBM2");
|
|
1642
|
-
IndexBinaryIDMap
|
|
1643
|
-
|
|
1644
|
-
|
|
1985
|
+
std::unique_ptr<IndexBinaryIDMap> idxmap = is_map2
|
|
1986
|
+
? std::make_unique<IndexBinaryIDMap2>()
|
|
1987
|
+
: std::make_unique<IndexBinaryIDMap>();
|
|
1988
|
+
read_index_binary_header(*idxmap, f);
|
|
1645
1989
|
idxmap->index = read_index_binary(f, io_flags);
|
|
1646
1990
|
idxmap->own_fields = true;
|
|
1647
1991
|
READVECTOR(idxmap->id_map);
|
|
1648
1992
|
if (is_map2) {
|
|
1649
|
-
static_cast<IndexBinaryIDMap2*>(idxmap)->construct_rev_map();
|
|
1993
|
+
static_cast<IndexBinaryIDMap2*>(idxmap.get())->construct_rev_map();
|
|
1650
1994
|
}
|
|
1651
|
-
idx = idxmap;
|
|
1995
|
+
idx = std::move(idxmap);
|
|
1652
1996
|
} else if (h == fourcc("IBHh")) {
|
|
1653
|
-
|
|
1654
|
-
read_index_binary_header(idxh, f);
|
|
1997
|
+
auto idxh = std::make_unique<IndexBinaryHash>();
|
|
1998
|
+
read_index_binary_header(*idxh, f);
|
|
1655
1999
|
READ1(idxh->b);
|
|
1656
2000
|
READ1(idxh->nflip);
|
|
1657
2001
|
read_binary_hash_invlists(idxh->invlists, idxh->b, f);
|
|
1658
|
-
idx = idxh;
|
|
2002
|
+
idx = std::move(idxh);
|
|
1659
2003
|
} else if (h == fourcc("IBHm")) {
|
|
1660
|
-
|
|
1661
|
-
read_index_binary_header(idxmh, f);
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
2004
|
+
auto idxmh = std::make_unique<IndexBinaryMultiHash>();
|
|
2005
|
+
read_index_binary_header(*idxmh, f);
|
|
2006
|
+
auto storage_idx = read_index_binary_up(f);
|
|
2007
|
+
auto* flat_ptr = dynamic_cast<IndexBinaryFlat*>(storage_idx.get());
|
|
2008
|
+
FAISS_THROW_IF_NOT(flat_ptr && flat_ptr->ntotal == idxmh->ntotal);
|
|
2009
|
+
idxmh->storage = flat_ptr;
|
|
2010
|
+
storage_idx.release();
|
|
1665
2011
|
idxmh->own_fields = true;
|
|
1666
2012
|
READ1(idxmh->b);
|
|
1667
2013
|
READ1(idxmh->nhash);
|
|
@@ -1671,40 +2017,52 @@ IndexBinary* read_index_binary(IOReader* f, int io_flags) {
|
|
|
1671
2017
|
read_binary_multi_hash_map(
|
|
1672
2018
|
idxmh->maps[i], idxmh->b, idxmh->ntotal, f);
|
|
1673
2019
|
}
|
|
1674
|
-
idx = idxmh;
|
|
2020
|
+
idx = std::move(idxmh);
|
|
1675
2021
|
} else {
|
|
1676
2022
|
FAISS_THROW_FMT(
|
|
1677
2023
|
"Index type %08x (\"%s\") not recognized",
|
|
1678
2024
|
h,
|
|
1679
2025
|
fourcc_inv_printable(h).c_str());
|
|
1680
|
-
idx = nullptr;
|
|
1681
2026
|
}
|
|
1682
2027
|
return idx;
|
|
1683
2028
|
}
|
|
1684
2029
|
|
|
1685
|
-
IndexBinary* read_index_binary(
|
|
2030
|
+
IndexBinary* read_index_binary(IOReader* f, int io_flags) {
|
|
2031
|
+
return read_index_binary_up(f, io_flags).release();
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
std::unique_ptr<IndexBinary> read_index_binary_up(FILE* f, int io_flags) {
|
|
1686
2035
|
if ((io_flags & IO_FLAG_MMAP_IFC) == IO_FLAG_MMAP_IFC) {
|
|
1687
2036
|
// enable mmap-supporting IOReader
|
|
1688
2037
|
auto owner = std::make_shared<MmappedFileMappingOwner>(f);
|
|
1689
2038
|
MappedFileIOReader reader(owner);
|
|
1690
|
-
return
|
|
2039
|
+
return read_index_binary_up(&reader, io_flags);
|
|
1691
2040
|
} else {
|
|
1692
2041
|
FileIOReader reader(f);
|
|
1693
|
-
return
|
|
2042
|
+
return read_index_binary_up(&reader, io_flags);
|
|
1694
2043
|
}
|
|
1695
2044
|
}
|
|
1696
2045
|
|
|
1697
|
-
IndexBinary* read_index_binary(
|
|
2046
|
+
IndexBinary* read_index_binary(FILE* f, int io_flags) {
|
|
2047
|
+
return read_index_binary_up(f, io_flags).release();
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
std::unique_ptr<IndexBinary> read_index_binary_up(
|
|
2051
|
+
const char* fname,
|
|
2052
|
+
int io_flags) {
|
|
1698
2053
|
if ((io_flags & IO_FLAG_MMAP_IFC) == IO_FLAG_MMAP_IFC) {
|
|
1699
2054
|
// enable mmap-supporting IOReader
|
|
1700
2055
|
auto owner = std::make_shared<MmappedFileMappingOwner>(fname);
|
|
1701
2056
|
MappedFileIOReader reader(owner);
|
|
1702
|
-
return
|
|
2057
|
+
return read_index_binary_up(&reader, io_flags);
|
|
1703
2058
|
} else {
|
|
1704
2059
|
FileIOReader reader(fname);
|
|
1705
|
-
|
|
1706
|
-
return idx;
|
|
2060
|
+
return read_index_binary_up(&reader, io_flags);
|
|
1707
2061
|
}
|
|
1708
2062
|
}
|
|
1709
2063
|
|
|
2064
|
+
IndexBinary* read_index_binary(const char* fname, int io_flags) {
|
|
2065
|
+
return read_index_binary_up(fname, io_flags).release();
|
|
2066
|
+
}
|
|
2067
|
+
|
|
1710
2068
|
} // namespace faiss
|