faiss 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +23 -21
- data/ext/faiss/extconf.rb +11 -0
- data/ext/faiss/index.cpp +4 -4
- data/ext/faiss/index_binary.cpp +6 -6
- data/ext/faiss/product_quantizer.cpp +4 -4
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +13 -0
- data/vendor/faiss/faiss/IVFlib.cpp +101 -2
- data/vendor/faiss/faiss/IVFlib.h +26 -2
- data/vendor/faiss/faiss/Index.cpp +36 -3
- data/vendor/faiss/faiss/Index.h +43 -6
- data/vendor/faiss/faiss/Index2Layer.cpp +6 -2
- data/vendor/faiss/faiss/Index2Layer.h +6 -1
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +219 -16
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +63 -5
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +299 -0
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +199 -0
- data/vendor/faiss/faiss/IndexBinary.cpp +20 -4
- data/vendor/faiss/faiss/IndexBinary.h +18 -3
- data/vendor/faiss/faiss/IndexBinaryFlat.cpp +9 -2
- data/vendor/faiss/faiss/IndexBinaryFlat.h +4 -2
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -1
- data/vendor/faiss/faiss/IndexBinaryFromFloat.h +2 -1
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +5 -1
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +2 -1
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +17 -4
- data/vendor/faiss/faiss/IndexBinaryHash.h +8 -4
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +28 -13
- data/vendor/faiss/faiss/IndexBinaryIVF.h +10 -7
- data/vendor/faiss/faiss/IndexFastScan.cpp +626 -0
- data/vendor/faiss/faiss/IndexFastScan.h +145 -0
- data/vendor/faiss/faiss/IndexFlat.cpp +34 -21
- data/vendor/faiss/faiss/IndexFlat.h +7 -4
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +35 -1
- data/vendor/faiss/faiss/IndexFlatCodes.h +12 -0
- data/vendor/faiss/faiss/IndexHNSW.cpp +66 -138
- data/vendor/faiss/faiss/IndexHNSW.h +4 -2
- data/vendor/faiss/faiss/IndexIDMap.cpp +247 -0
- data/vendor/faiss/faiss/IndexIDMap.h +107 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +121 -33
- data/vendor/faiss/faiss/IndexIVF.h +35 -16
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +84 -7
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +63 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +590 -0
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +171 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +1290 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.h +213 -0
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +37 -17
- data/vendor/faiss/faiss/IndexIVFFlat.h +4 -2
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +234 -50
- data/vendor/faiss/faiss/IndexIVFPQ.h +5 -1
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +23 -852
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +7 -112
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFPQR.h +1 -1
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +3 -1
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +2 -1
- data/vendor/faiss/faiss/IndexLSH.cpp +4 -2
- data/vendor/faiss/faiss/IndexLSH.h +2 -1
- data/vendor/faiss/faiss/IndexLattice.cpp +7 -1
- data/vendor/faiss/faiss/IndexLattice.h +3 -1
- data/vendor/faiss/faiss/IndexNNDescent.cpp +4 -3
- data/vendor/faiss/faiss/IndexNNDescent.h +2 -1
- data/vendor/faiss/faiss/IndexNSG.cpp +37 -3
- data/vendor/faiss/faiss/IndexNSG.h +25 -1
- data/vendor/faiss/faiss/IndexPQ.cpp +106 -69
- data/vendor/faiss/faiss/IndexPQ.h +19 -5
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +15 -450
- data/vendor/faiss/faiss/IndexPQFastScan.h +15 -78
- data/vendor/faiss/faiss/IndexPreTransform.cpp +47 -8
- data/vendor/faiss/faiss/IndexPreTransform.h +15 -3
- data/vendor/faiss/faiss/IndexRefine.cpp +8 -4
- data/vendor/faiss/faiss/IndexRefine.h +4 -2
- data/vendor/faiss/faiss/IndexReplicas.cpp +4 -2
- data/vendor/faiss/faiss/IndexReplicas.h +2 -1
- data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +438 -0
- data/vendor/faiss/faiss/IndexRowwiseMinMax.h +92 -0
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +26 -15
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +6 -7
- data/vendor/faiss/faiss/IndexShards.cpp +4 -1
- data/vendor/faiss/faiss/IndexShards.h +2 -1
- data/vendor/faiss/faiss/MetaIndexes.cpp +5 -178
- data/vendor/faiss/faiss/MetaIndexes.h +3 -81
- data/vendor/faiss/faiss/VectorTransform.cpp +43 -0
- data/vendor/faiss/faiss/VectorTransform.h +22 -4
- data/vendor/faiss/faiss/clone_index.cpp +23 -1
- data/vendor/faiss/faiss/clone_index.h +3 -0
- data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +300 -0
- data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +24 -0
- data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +195 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +2058 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +408 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +2147 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +460 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +465 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +1618 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +251 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +1452 -0
- data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +1 -0
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +0 -4
- data/vendor/faiss/faiss/gpu/GpuIndex.h +28 -4
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +2 -1
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +10 -8
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +75 -14
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +19 -32
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -31
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +22 -28
- data/vendor/faiss/faiss/gpu/GpuResources.cpp +14 -0
- data/vendor/faiss/faiss/gpu/GpuResources.h +16 -3
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +3 -3
- data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +32 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +1 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +311 -75
- data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +10 -0
- data/vendor/faiss/faiss/gpu/test/TestUtils.h +3 -0
- data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +2 -2
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +5 -4
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +116 -47
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +44 -13
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +0 -54
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +0 -76
- data/vendor/faiss/faiss/impl/DistanceComputer.h +64 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +123 -27
- data/vendor/faiss/faiss/impl/HNSW.h +19 -16
- data/vendor/faiss/faiss/impl/IDSelector.cpp +125 -0
- data/vendor/faiss/faiss/impl/IDSelector.h +135 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +6 -28
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +6 -1
- data/vendor/faiss/faiss/impl/LookupTableScaler.h +77 -0
- data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -0
- data/vendor/faiss/faiss/impl/NSG.cpp +1 -1
- data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +383 -0
- data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +154 -0
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +225 -145
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +29 -10
- data/vendor/faiss/faiss/impl/Quantizer.h +43 -0
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +192 -36
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +40 -20
- data/vendor/faiss/faiss/impl/ResultHandler.h +96 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +97 -173
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +18 -18
- data/vendor/faiss/faiss/impl/index_read.cpp +240 -9
- data/vendor/faiss/faiss/impl/index_write.cpp +237 -5
- data/vendor/faiss/faiss/impl/kmeans1d.cpp +6 -4
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +56 -16
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +25 -8
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +66 -25
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +75 -27
- data/vendor/faiss/faiss/index_factory.cpp +196 -7
- data/vendor/faiss/faiss/index_io.h +5 -0
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -0
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +4 -1
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +2 -1
- data/vendor/faiss/faiss/python/python_callbacks.cpp +27 -0
- data/vendor/faiss/faiss/python/python_callbacks.h +15 -0
- data/vendor/faiss/faiss/utils/Heap.h +31 -15
- data/vendor/faiss/faiss/utils/distances.cpp +380 -56
- data/vendor/faiss/faiss/utils/distances.h +113 -15
- data/vendor/faiss/faiss/utils/distances_simd.cpp +726 -6
- data/vendor/faiss/faiss/utils/extra_distances.cpp +12 -7
- data/vendor/faiss/faiss/utils/extra_distances.h +3 -1
- data/vendor/faiss/faiss/utils/fp16-fp16c.h +21 -0
- data/vendor/faiss/faiss/utils/fp16-inl.h +101 -0
- data/vendor/faiss/faiss/utils/fp16.h +11 -0
- data/vendor/faiss/faiss/utils/hamming-inl.h +54 -0
- data/vendor/faiss/faiss/utils/hamming.cpp +0 -48
- data/vendor/faiss/faiss/utils/ordered_key_value.h +10 -0
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +62 -0
- data/vendor/faiss/faiss/utils/quantize_lut.h +20 -0
- data/vendor/faiss/faiss/utils/random.cpp +53 -0
- data/vendor/faiss/faiss/utils/random.h +5 -0
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +4 -0
- data/vendor/faiss/faiss/utils/simdlib_emulated.h +6 -1
- data/vendor/faiss/faiss/utils/simdlib_neon.h +7 -2
- metadata +37 -3
|
@@ -26,10 +26,12 @@
|
|
|
26
26
|
|
|
27
27
|
#include <faiss/Index2Layer.h>
|
|
28
28
|
#include <faiss/IndexAdditiveQuantizer.h>
|
|
29
|
+
#include <faiss/IndexAdditiveQuantizerFastScan.h>
|
|
29
30
|
#include <faiss/IndexFlat.h>
|
|
30
31
|
#include <faiss/IndexHNSW.h>
|
|
31
32
|
#include <faiss/IndexIVF.h>
|
|
32
33
|
#include <faiss/IndexIVFAdditiveQuantizer.h>
|
|
34
|
+
#include <faiss/IndexIVFAdditiveQuantizerFastScan.h>
|
|
33
35
|
#include <faiss/IndexIVFFlat.h>
|
|
34
36
|
#include <faiss/IndexIVFPQ.h>
|
|
35
37
|
#include <faiss/IndexIVFPQFastScan.h>
|
|
@@ -42,6 +44,7 @@
|
|
|
42
44
|
#include <faiss/IndexPQFastScan.h>
|
|
43
45
|
#include <faiss/IndexPreTransform.h>
|
|
44
46
|
#include <faiss/IndexRefine.h>
|
|
47
|
+
#include <faiss/IndexRowwiseMinMax.h>
|
|
45
48
|
#include <faiss/IndexScalarQuantizer.h>
|
|
46
49
|
#include <faiss/MetaIndexes.h>
|
|
47
50
|
#include <faiss/VectorTransform.h>
|
|
@@ -149,11 +152,15 @@ std::map<std::string, AdditiveQuantizer::Search_type_t> aq_search_type = {
|
|
|
149
152
|
{"_Nqint4", AdditiveQuantizer::ST_norm_qint4},
|
|
150
153
|
{"_Ncqint8", AdditiveQuantizer::ST_norm_cqint8},
|
|
151
154
|
{"_Ncqint4", AdditiveQuantizer::ST_norm_cqint4},
|
|
155
|
+
{"_Nlsq2x4", AdditiveQuantizer::ST_norm_lsq2x4},
|
|
156
|
+
{"_Nrq2x4", AdditiveQuantizer::ST_norm_rq2x4},
|
|
152
157
|
};
|
|
153
158
|
|
|
154
159
|
const std::string aq_def_pattern = "[0-9]+x[0-9]+(_[0-9]+x[0-9]+)*";
|
|
155
160
|
const std::string aq_norm_pattern =
|
|
156
|
-
"(|_Nnone|_Nfloat|_Nqint8|_Nqint4|_Ncqint8|_Ncqint4)";
|
|
161
|
+
"(|_Nnone|_Nfloat|_Nqint8|_Nqint4|_Ncqint8|_Ncqint4|_Nlsq2x4|_Nrq2x4)";
|
|
162
|
+
|
|
163
|
+
const std::string paq_def_pattern = "([0-9]+)x([0-9]+)x([0-9]+)";
|
|
157
164
|
|
|
158
165
|
AdditiveQuantizer::Search_type_t aq_parse_search_type(
|
|
159
166
|
std::string stok,
|
|
@@ -169,7 +176,7 @@ AdditiveQuantizer::Search_type_t aq_parse_search_type(
|
|
|
169
176
|
std::vector<size_t> aq_parse_nbits(std::string stok) {
|
|
170
177
|
std::vector<size_t> nbits;
|
|
171
178
|
std::smatch sm;
|
|
172
|
-
while (std::regex_search(stok, sm, std::regex("([0-9]+)x([0-9]+)"))) {
|
|
179
|
+
while (std::regex_search(stok, sm, std::regex("[^q]([0-9]+)x([0-9]+)"))) {
|
|
173
180
|
int M = std::stoi(sm[1].str());
|
|
174
181
|
int nbit = std::stoi(sm[2].str());
|
|
175
182
|
nbits.resize(nbits.size() + M, nbit);
|
|
@@ -341,6 +348,53 @@ IndexIVF* parse_IndexIVF(
|
|
|
341
348
|
}
|
|
342
349
|
return index_ivf;
|
|
343
350
|
}
|
|
351
|
+
if (match("(PRQ|PLSQ)" + paq_def_pattern + aq_norm_pattern)) {
|
|
352
|
+
int nsplits = mres_to_int(sm[2]);
|
|
353
|
+
int Msub = mres_to_int(sm[3]);
|
|
354
|
+
int nbit = mres_to_int(sm[4]);
|
|
355
|
+
auto st = aq_parse_search_type(sm[sm.size() - 1].str(), mt);
|
|
356
|
+
IndexIVF* index_ivf;
|
|
357
|
+
if (sm[1].str() == "PRQ") {
|
|
358
|
+
index_ivf = new IndexIVFProductResidualQuantizer(
|
|
359
|
+
get_q(), d, nlist, nsplits, Msub, nbit, mt, st);
|
|
360
|
+
} else {
|
|
361
|
+
index_ivf = new IndexIVFProductLocalSearchQuantizer(
|
|
362
|
+
get_q(), d, nlist, nsplits, Msub, nbit, mt, st);
|
|
363
|
+
}
|
|
364
|
+
return index_ivf;
|
|
365
|
+
}
|
|
366
|
+
if (match("(RQ|LSQ)([0-9]+)x4fs(r?)(_[0-9]+)?" + aq_norm_pattern)) {
|
|
367
|
+
int M = std::stoi(sm[2].str());
|
|
368
|
+
int bbs = mres_to_int(sm[4], 32, 1);
|
|
369
|
+
auto st = aq_parse_search_type(sm[sm.size() - 1].str(), mt);
|
|
370
|
+
IndexIVFAdditiveQuantizerFastScan* index_ivf;
|
|
371
|
+
if (sm[1].str() == "RQ") {
|
|
372
|
+
index_ivf = new IndexIVFResidualQuantizerFastScan(
|
|
373
|
+
get_q(), d, nlist, M, 4, mt, st, bbs);
|
|
374
|
+
} else {
|
|
375
|
+
index_ivf = new IndexIVFLocalSearchQuantizerFastScan(
|
|
376
|
+
get_q(), d, nlist, M, 4, mt, st, bbs);
|
|
377
|
+
}
|
|
378
|
+
index_ivf->by_residual = (sm[3].str() == "r");
|
|
379
|
+
return index_ivf;
|
|
380
|
+
}
|
|
381
|
+
if (match("(PRQ|PLSQ)([0-9]+)x([0-9]+)x4fs(r?)(_[0-9]+)?" +
|
|
382
|
+
aq_norm_pattern)) {
|
|
383
|
+
int nsplits = std::stoi(sm[2].str());
|
|
384
|
+
int Msub = std::stoi(sm[3].str());
|
|
385
|
+
int bbs = mres_to_int(sm[5], 32, 1);
|
|
386
|
+
auto st = aq_parse_search_type(sm[sm.size() - 1].str(), mt);
|
|
387
|
+
IndexIVFAdditiveQuantizerFastScan* index_ivf;
|
|
388
|
+
if (sm[1].str() == "PRQ") {
|
|
389
|
+
index_ivf = new IndexIVFProductResidualQuantizerFastScan(
|
|
390
|
+
get_q(), d, nlist, nsplits, Msub, 4, mt, st, bbs);
|
|
391
|
+
} else {
|
|
392
|
+
index_ivf = new IndexIVFProductLocalSearchQuantizerFastScan(
|
|
393
|
+
get_q(), d, nlist, nsplits, Msub, 4, mt, st, bbs);
|
|
394
|
+
}
|
|
395
|
+
index_ivf->by_residual = (sm[4].str() == "r");
|
|
396
|
+
return index_ivf;
|
|
397
|
+
}
|
|
344
398
|
if (match("(ITQ|PCA|PCAR)([0-9]+)?,SH([-0-9.e]+)?([gcm])?")) {
|
|
345
399
|
int outdim = mres_to_int(sm[2], d); // is also the number of bits
|
|
346
400
|
std::unique_ptr<VectorTransform> vt;
|
|
@@ -421,6 +475,37 @@ IndexHNSW* parse_IndexHNSW(
|
|
|
421
475
|
return nullptr;
|
|
422
476
|
}
|
|
423
477
|
|
|
478
|
+
/***************************************************************
|
|
479
|
+
* Parse IndexNSG
|
|
480
|
+
*/
|
|
481
|
+
|
|
482
|
+
IndexNSG* parse_IndexNSG(
|
|
483
|
+
const std::string code_string,
|
|
484
|
+
int d,
|
|
485
|
+
MetricType mt,
|
|
486
|
+
int nsg_R) {
|
|
487
|
+
std::smatch sm;
|
|
488
|
+
auto match = [&sm, &code_string](const std::string& pattern) {
|
|
489
|
+
return re_match(code_string, pattern, sm);
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
if (match("Flat|")) {
|
|
493
|
+
return new IndexNSGFlat(d, nsg_R, mt);
|
|
494
|
+
}
|
|
495
|
+
if (match("PQ([0-9]+)(np)?")) {
|
|
496
|
+
int M = std::stoi(sm[1].str());
|
|
497
|
+
IndexNSGPQ* ipq = new IndexNSGPQ(d, M, nsg_R);
|
|
498
|
+
dynamic_cast<IndexPQ*>(ipq->storage)->do_polysemous_training =
|
|
499
|
+
sm[2].str() != "np";
|
|
500
|
+
return ipq;
|
|
501
|
+
}
|
|
502
|
+
if (match(sq_pattern)) {
|
|
503
|
+
return new IndexNSGSQ(d, sq_types[sm[1].str()], nsg_R, mt);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
return nullptr;
|
|
507
|
+
}
|
|
508
|
+
|
|
424
509
|
/***************************************************************
|
|
425
510
|
* Parse basic indexes
|
|
426
511
|
*/
|
|
@@ -454,11 +539,6 @@ Index* parse_other_indexes(
|
|
|
454
539
|
return new IndexLattice(d, M, nbit, r2);
|
|
455
540
|
}
|
|
456
541
|
|
|
457
|
-
// IndexNSGFlat
|
|
458
|
-
if (match("NSG([0-9]+)(,Flat)?")) {
|
|
459
|
-
return new IndexNSGFlat(d, std::stoi(sm[1].str()), metric);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
542
|
// IndexScalarQuantizer
|
|
463
543
|
if (match(sq_pattern)) {
|
|
464
544
|
return new IndexScalarQuantizer(d, sq_types[description], metric);
|
|
@@ -505,6 +585,60 @@ Index* parse_other_indexes(
|
|
|
505
585
|
return new IndexLocalSearchQuantizer(d, M, nbit, metric, st);
|
|
506
586
|
}
|
|
507
587
|
|
|
588
|
+
// IndexProductResidualQuantizer
|
|
589
|
+
if (match("PRQ" + paq_def_pattern + aq_norm_pattern)) {
|
|
590
|
+
int nsplits = mres_to_int(sm[1]);
|
|
591
|
+
int Msub = mres_to_int(sm[2]);
|
|
592
|
+
int nbit = mres_to_int(sm[3]);
|
|
593
|
+
auto st = aq_parse_search_type(sm[sm.size() - 1].str(), metric);
|
|
594
|
+
return new IndexProductResidualQuantizer(
|
|
595
|
+
d, nsplits, Msub, nbit, metric, st);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// IndexProductLocalSearchQuantizer
|
|
599
|
+
if (match("PLSQ" + paq_def_pattern + aq_norm_pattern)) {
|
|
600
|
+
int nsplits = mres_to_int(sm[1]);
|
|
601
|
+
int Msub = mres_to_int(sm[2]);
|
|
602
|
+
int nbit = mres_to_int(sm[3]);
|
|
603
|
+
auto st = aq_parse_search_type(sm[sm.size() - 1].str(), metric);
|
|
604
|
+
return new IndexProductLocalSearchQuantizer(
|
|
605
|
+
d, nsplits, Msub, nbit, metric, st);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// IndexAdditiveQuantizerFastScan
|
|
609
|
+
// RQ{M}x4fs_{bbs}_{search_type}
|
|
610
|
+
pattern = "(LSQ|RQ)([0-9]+)x4fs(_[0-9]+)?" + aq_norm_pattern;
|
|
611
|
+
if (match(pattern)) {
|
|
612
|
+
int M = std::stoi(sm[2].str());
|
|
613
|
+
int bbs = mres_to_int(sm[3], 32, 1);
|
|
614
|
+
auto st = aq_parse_search_type(sm[sm.size() - 1].str(), metric);
|
|
615
|
+
|
|
616
|
+
if (sm[1].str() == "RQ") {
|
|
617
|
+
return new IndexResidualQuantizerFastScan(d, M, 4, metric, st, bbs);
|
|
618
|
+
} else if (sm[1].str() == "LSQ") {
|
|
619
|
+
return new IndexLocalSearchQuantizerFastScan(
|
|
620
|
+
d, M, 4, metric, st, bbs);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// IndexProductAdditiveQuantizerFastScan
|
|
625
|
+
// PRQ{nsplits}x{Msub}x4fs_{bbs}_{search_type}
|
|
626
|
+
pattern = "(PLSQ|PRQ)([0-9]+)x([0-9]+)x4fs(_[0-9]+)?" + aq_norm_pattern;
|
|
627
|
+
if (match(pattern)) {
|
|
628
|
+
int nsplits = std::stoi(sm[2].str());
|
|
629
|
+
int Msub = std::stoi(sm[3].str());
|
|
630
|
+
int bbs = mres_to_int(sm[4], 32, 1);
|
|
631
|
+
auto st = aq_parse_search_type(sm[sm.size() - 1].str(), metric);
|
|
632
|
+
|
|
633
|
+
if (sm[1].str() == "PRQ") {
|
|
634
|
+
return new IndexProductResidualQuantizerFastScan(
|
|
635
|
+
d, nsplits, Msub, 4, metric, st, bbs);
|
|
636
|
+
} else if (sm[1].str() == "PLSQ") {
|
|
637
|
+
return new IndexProductLocalSearchQuantizerFastScan(
|
|
638
|
+
d, nsplits, Msub, 4, metric, st, bbs);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
508
642
|
return nullptr;
|
|
509
643
|
}
|
|
510
644
|
|
|
@@ -604,6 +738,14 @@ std::unique_ptr<Index> index_factory_sub(
|
|
|
604
738
|
|
|
605
739
|
// IndexIDMap -- it turns out is was used both as a prefix and a suffix, so
|
|
606
740
|
// support both
|
|
741
|
+
if (re_match(description, "(.+),IDMap2", sm) ||
|
|
742
|
+
re_match(description, "IDMap2,(.+)", sm)) {
|
|
743
|
+
IndexIDMap2* idmap2 = new IndexIDMap2(
|
|
744
|
+
index_factory_sub(d, sm[1].str(), metric).release());
|
|
745
|
+
idmap2->own_fields = true;
|
|
746
|
+
return std::unique_ptr<Index>(idmap2);
|
|
747
|
+
}
|
|
748
|
+
|
|
607
749
|
if (re_match(description, "(.+),IDMap", sm) ||
|
|
608
750
|
re_match(description, "IDMap,(.+)", sm)) {
|
|
609
751
|
IndexIDMap* idmap = new IndexIDMap(
|
|
@@ -642,6 +784,53 @@ std::unique_ptr<Index> index_factory_sub(
|
|
|
642
784
|
return std::unique_ptr<Index>(index);
|
|
643
785
|
}
|
|
644
786
|
|
|
787
|
+
// NSG variants (it was unclear in the old version that the separator was a
|
|
788
|
+
// "," so we support both "_" and ",")
|
|
789
|
+
if (re_match(description, "NSG([0-9]*)([,_].*)?", sm)) {
|
|
790
|
+
int nsg_R = mres_to_int(sm[1], 32);
|
|
791
|
+
// We also accept empty code string (synonym of Flat)
|
|
792
|
+
std::string code_string =
|
|
793
|
+
sm[2].length() > 0 ? sm[2].str().substr(1) : "";
|
|
794
|
+
if (verbose) {
|
|
795
|
+
printf("parsing NSG string %s code_string=%s nsg_R=%d\n",
|
|
796
|
+
description.c_str(),
|
|
797
|
+
code_string.c_str(),
|
|
798
|
+
nsg_R);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
IndexNSG* index = parse_IndexNSG(code_string, d, metric, nsg_R);
|
|
802
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
803
|
+
index,
|
|
804
|
+
"could not parse NSG code description %s in %s",
|
|
805
|
+
code_string.c_str(),
|
|
806
|
+
description.c_str());
|
|
807
|
+
return std::unique_ptr<Index>(index);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// IndexRowwiseMinMax, fp32 version
|
|
811
|
+
if (description.compare(0, 7, "MinMax,") == 0) {
|
|
812
|
+
size_t comma = description.find(",");
|
|
813
|
+
std::string sub_index_string = description.substr(comma + 1);
|
|
814
|
+
auto sub_index = index_factory_sub(d, sub_index_string, metric);
|
|
815
|
+
|
|
816
|
+
auto index = new IndexRowwiseMinMax(sub_index.release());
|
|
817
|
+
index->own_fields = true;
|
|
818
|
+
|
|
819
|
+
return std::unique_ptr<Index>(index);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// IndexRowwiseMinMax, fp16 version
|
|
823
|
+
if (description.compare(0, 11, "MinMaxFP16,") == 0) {
|
|
824
|
+
size_t comma = description.find(",");
|
|
825
|
+
std::string sub_index_string = description.substr(comma + 1);
|
|
826
|
+
auto sub_index = index_factory_sub(d, sub_index_string, metric);
|
|
827
|
+
|
|
828
|
+
auto index = new IndexRowwiseMinMaxFP16(sub_index.release());
|
|
829
|
+
index->own_fields = true;
|
|
830
|
+
|
|
831
|
+
return std::unique_ptr<Index>(index);
|
|
832
|
+
}
|
|
833
|
+
|
|
645
834
|
// IndexIVF
|
|
646
835
|
{
|
|
647
836
|
size_t nlist;
|
|
@@ -50,6 +50,8 @@ const int IO_FLAG_READ_ONLY = 2;
|
|
|
50
50
|
const int IO_FLAG_ONDISK_SAME_DIR = 4;
|
|
51
51
|
// don't load IVF data to RAM, only list sizes
|
|
52
52
|
const int IO_FLAG_SKIP_IVF_DATA = 8;
|
|
53
|
+
// don't initialize precomputed table after loading
|
|
54
|
+
const int IO_FLAG_SKIP_PRECOMPUTE_TABLE = 16;
|
|
53
55
|
// try to memmap data (useful to load an ArrayInvertedLists as an
|
|
54
56
|
// OnDiskInvertedLists)
|
|
55
57
|
const int IO_FLAG_MMAP = IO_FLAG_SKIP_IVF_DATA | 0x646f0000;
|
|
@@ -63,7 +65,10 @@ IndexBinary* read_index_binary(FILE* f, int io_flags = 0);
|
|
|
63
65
|
IndexBinary* read_index_binary(IOReader* reader, int io_flags = 0);
|
|
64
66
|
|
|
65
67
|
void write_VectorTransform(const VectorTransform* vt, const char* fname);
|
|
68
|
+
void write_VectorTransform(const VectorTransform* vt, IOWriter* f);
|
|
69
|
+
|
|
66
70
|
VectorTransform* read_VectorTransform(const char* fname);
|
|
71
|
+
VectorTransform* read_VectorTransform(IOReader* f);
|
|
67
72
|
|
|
68
73
|
ProductQuantizer* read_ProductQuantizer(const char* fname);
|
|
69
74
|
ProductQuantizer* read_ProductQuantizer(IOReader* reader);
|
|
@@ -28,7 +28,10 @@ InvertedLists::~InvertedLists() {}
|
|
|
28
28
|
InvertedLists::idx_t InvertedLists::get_single_id(size_t list_no, size_t offset)
|
|
29
29
|
const {
|
|
30
30
|
assert(offset < list_size(list_no));
|
|
31
|
-
|
|
31
|
+
const idx_t* ids = get_ids(list_no);
|
|
32
|
+
idx_t id = ids[offset];
|
|
33
|
+
release_ids(list_no, ids);
|
|
34
|
+
return id;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
void InvertedLists::release_codes(size_t, const uint8_t*) const {}
|
|
@@ -278,13 +278,14 @@ void OnDiskInvertedLists::do_mmap() {
|
|
|
278
278
|
uint8_t* ptro =
|
|
279
279
|
(uint8_t*)mmap(nullptr, totsize, prot, MAP_SHARED, fileno(f), 0);
|
|
280
280
|
|
|
281
|
+
fclose(f);
|
|
282
|
+
|
|
281
283
|
FAISS_THROW_IF_NOT_FMT(
|
|
282
284
|
ptro != MAP_FAILED,
|
|
283
285
|
"could not mmap %s: %s",
|
|
284
286
|
filename.c_str(),
|
|
285
287
|
strerror(errno));
|
|
286
288
|
ptr = ptro;
|
|
287
|
-
fclose(f);
|
|
288
289
|
}
|
|
289
290
|
|
|
290
291
|
void OnDiskInvertedLists::update_totsize(size_t new_size) {
|
|
@@ -107,3 +107,30 @@ PyCallbackIOReader::~PyCallbackIOReader() {
|
|
|
107
107
|
PyThreadLock gil;
|
|
108
108
|
Py_DECREF(callback);
|
|
109
109
|
}
|
|
110
|
+
|
|
111
|
+
/***********************************************************
|
|
112
|
+
* Callbacks for IDSelector
|
|
113
|
+
***********************************************************/
|
|
114
|
+
|
|
115
|
+
PyCallbackIDSelector::PyCallbackIDSelector(PyObject* callback)
|
|
116
|
+
: callback(callback) {
|
|
117
|
+
PyThreadLock gil;
|
|
118
|
+
Py_INCREF(callback);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
bool PyCallbackIDSelector::is_member(idx_t id) const {
|
|
122
|
+
FAISS_THROW_IF_NOT((id >> 32) == 0);
|
|
123
|
+
PyThreadLock gil;
|
|
124
|
+
PyObject* result = PyObject_CallFunction(callback, "(n)", int(id));
|
|
125
|
+
if (result == NULL) {
|
|
126
|
+
FAISS_THROW_MSG("propagate py error");
|
|
127
|
+
}
|
|
128
|
+
bool b = PyObject_IsTrue(result);
|
|
129
|
+
Py_DECREF(result);
|
|
130
|
+
return b;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
PyCallbackIDSelector::~PyCallbackIDSelector() {
|
|
134
|
+
PyThreadLock gil;
|
|
135
|
+
Py_DECREF(callback);
|
|
136
|
+
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include <faiss/impl/IDSelector.h>
|
|
10
11
|
#include <faiss/impl/io.h>
|
|
11
12
|
#include <faiss/invlists/InvertedLists.h>
|
|
12
13
|
#include "Python.h"
|
|
@@ -43,3 +44,17 @@ struct PyCallbackIOReader : faiss::IOReader {
|
|
|
43
44
|
|
|
44
45
|
~PyCallbackIOReader() override;
|
|
45
46
|
};
|
|
47
|
+
|
|
48
|
+
/***********************************************************
|
|
49
|
+
* Callbacks for IDSelector
|
|
50
|
+
***********************************************************/
|
|
51
|
+
|
|
52
|
+
struct PyCallbackIDSelector : faiss::IDSelector {
|
|
53
|
+
PyObject* callback;
|
|
54
|
+
|
|
55
|
+
explicit PyCallbackIDSelector(PyObject* callback);
|
|
56
|
+
|
|
57
|
+
bool is_member(idx_t id) const override;
|
|
58
|
+
|
|
59
|
+
~PyCallbackIDSelector() override;
|
|
60
|
+
};
|
|
@@ -47,21 +47,25 @@ inline void heap_pop(size_t k, typename C::T* bh_val, typename C::TI* bh_ids) {
|
|
|
47
47
|
bh_val--; /* Use 1-based indexing for easier node->child translation */
|
|
48
48
|
bh_ids--;
|
|
49
49
|
typename C::T val = bh_val[k];
|
|
50
|
+
typename C::TI id = bh_ids[k];
|
|
50
51
|
size_t i = 1, i1, i2;
|
|
51
52
|
while (1) {
|
|
52
53
|
i1 = i << 1;
|
|
53
54
|
i2 = i1 + 1;
|
|
54
55
|
if (i1 > k)
|
|
55
56
|
break;
|
|
56
|
-
if (i2 == k + 1 ||
|
|
57
|
-
|
|
57
|
+
if ((i2 == k + 1) ||
|
|
58
|
+
C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
|
|
59
|
+
if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
|
|
58
60
|
break;
|
|
61
|
+
}
|
|
59
62
|
bh_val[i] = bh_val[i1];
|
|
60
63
|
bh_ids[i] = bh_ids[i1];
|
|
61
64
|
i = i1;
|
|
62
65
|
} else {
|
|
63
|
-
if (C::
|
|
66
|
+
if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
|
|
64
67
|
break;
|
|
68
|
+
}
|
|
65
69
|
bh_val[i] = bh_val[i2];
|
|
66
70
|
bh_ids[i] = bh_ids[i2];
|
|
67
71
|
i = i2;
|
|
@@ -80,24 +84,28 @@ inline void heap_push(
|
|
|
80
84
|
typename C::T* bh_val,
|
|
81
85
|
typename C::TI* bh_ids,
|
|
82
86
|
typename C::T val,
|
|
83
|
-
typename C::TI
|
|
87
|
+
typename C::TI id) {
|
|
84
88
|
bh_val--; /* Use 1-based indexing for easier node->child translation */
|
|
85
89
|
bh_ids--;
|
|
86
90
|
size_t i = k, i_father;
|
|
87
91
|
while (i > 1) {
|
|
88
92
|
i_father = i >> 1;
|
|
89
|
-
if (!C::
|
|
93
|
+
if (!C::cmp2(val, bh_val[i_father], id, bh_ids[i_father])) {
|
|
94
|
+
/* the heap structure is ok */
|
|
90
95
|
break;
|
|
96
|
+
}
|
|
91
97
|
bh_val[i] = bh_val[i_father];
|
|
92
98
|
bh_ids[i] = bh_ids[i_father];
|
|
93
99
|
i = i_father;
|
|
94
100
|
}
|
|
95
101
|
bh_val[i] = val;
|
|
96
|
-
bh_ids[i] =
|
|
102
|
+
bh_ids[i] = id;
|
|
97
103
|
}
|
|
98
104
|
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
105
|
+
/**
|
|
106
|
+
* Replaces the top element from the heap defined by bh_val[0..k-1] and
|
|
107
|
+
* bh_ids[0..k-1], and for identical bh_val[] values also sorts by bh_ids[]
|
|
108
|
+
* values.
|
|
101
109
|
*/
|
|
102
110
|
template <class C>
|
|
103
111
|
inline void heap_replace_top(
|
|
@@ -105,31 +113,39 @@ inline void heap_replace_top(
|
|
|
105
113
|
typename C::T* bh_val,
|
|
106
114
|
typename C::TI* bh_ids,
|
|
107
115
|
typename C::T val,
|
|
108
|
-
typename C::TI
|
|
116
|
+
typename C::TI id) {
|
|
109
117
|
bh_val--; /* Use 1-based indexing for easier node->child translation */
|
|
110
118
|
bh_ids--;
|
|
111
119
|
size_t i = 1, i1, i2;
|
|
112
120
|
while (1) {
|
|
113
121
|
i1 = i << 1;
|
|
114
122
|
i2 = i1 + 1;
|
|
115
|
-
if (i1 > k)
|
|
123
|
+
if (i1 > k) {
|
|
116
124
|
break;
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Note that C::cmp2() is a bool function answering
|
|
128
|
+
// `(a1 > b1) || ((a1 == b1) && (a2 > b2))` for max
|
|
129
|
+
// heap and same with the `<` sign for min heap.
|
|
130
|
+
if ((i2 == k + 1) ||
|
|
131
|
+
C::cmp2(bh_val[i1], bh_val[i2], bh_ids[i1], bh_ids[i2])) {
|
|
132
|
+
if (C::cmp2(val, bh_val[i1], id, bh_ids[i1])) {
|
|
119
133
|
break;
|
|
134
|
+
}
|
|
120
135
|
bh_val[i] = bh_val[i1];
|
|
121
136
|
bh_ids[i] = bh_ids[i1];
|
|
122
137
|
i = i1;
|
|
123
138
|
} else {
|
|
124
|
-
if (C::
|
|
139
|
+
if (C::cmp2(val, bh_val[i2], id, bh_ids[i2])) {
|
|
125
140
|
break;
|
|
141
|
+
}
|
|
126
142
|
bh_val[i] = bh_val[i2];
|
|
127
143
|
bh_ids[i] = bh_ids[i2];
|
|
128
144
|
i = i2;
|
|
129
145
|
}
|
|
130
146
|
}
|
|
131
147
|
bh_val[i] = val;
|
|
132
|
-
bh_ids[i] =
|
|
148
|
+
bh_ids[i] = id;
|
|
133
149
|
}
|
|
134
150
|
|
|
135
151
|
/* Partial instanciation for heaps with TI = int64_t */
|
|
@@ -294,7 +310,7 @@ inline void maxheap_addn(
|
|
|
294
310
|
* Heap finalization (reorder elements)
|
|
295
311
|
*******************************************************************/
|
|
296
312
|
|
|
297
|
-
/* This function maps a binary heap into
|
|
313
|
+
/* This function maps a binary heap into a sorted structure.
|
|
298
314
|
It returns the number */
|
|
299
315
|
template <typename C>
|
|
300
316
|
inline size_t heap_reorder(
|