faiss 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +39 -29
- data/vendor/faiss/faiss/Clustering.cpp +4 -2
- data/vendor/faiss/faiss/IVFlib.cpp +14 -7
- data/vendor/faiss/faiss/Index.h +72 -3
- data/vendor/faiss/faiss/Index2Layer.cpp +2 -4
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +0 -1
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +1 -0
- data/vendor/faiss/faiss/IndexBinary.h +46 -3
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +118 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +41 -0
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +0 -1
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +18 -7
- data/vendor/faiss/faiss/IndexBinaryIVF.h +5 -1
- data/vendor/faiss/faiss/IndexFlat.cpp +6 -4
- data/vendor/faiss/faiss/IndexHNSW.cpp +65 -24
- data/vendor/faiss/faiss/IndexHNSW.h +10 -1
- data/vendor/faiss/faiss/IndexIDMap.cpp +96 -18
- data/vendor/faiss/faiss/IndexIDMap.h +20 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +28 -10
- data/vendor/faiss/faiss/IndexIVF.h +16 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +84 -16
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +18 -6
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +33 -21
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +16 -6
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +24 -15
- data/vendor/faiss/faiss/IndexIVFFastScan.h +4 -2
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +59 -43
- data/vendor/faiss/faiss/IndexIVFFlat.h +10 -2
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +16 -3
- data/vendor/faiss/faiss/IndexIVFPQ.h +8 -1
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +14 -6
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +2 -1
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +14 -4
- data/vendor/faiss/faiss/IndexIVFPQR.h +2 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +28 -3
- data/vendor/faiss/faiss/IndexIVFRaBitQ.h +8 -1
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +9 -2
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +2 -1
- data/vendor/faiss/faiss/IndexLattice.cpp +8 -4
- data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -7
- data/vendor/faiss/faiss/IndexNSG.cpp +3 -3
- data/vendor/faiss/faiss/IndexPQ.cpp +0 -1
- data/vendor/faiss/faiss/IndexPQ.h +1 -0
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +0 -2
- data/vendor/faiss/faiss/IndexPreTransform.cpp +4 -2
- data/vendor/faiss/faiss/IndexRefine.cpp +11 -6
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +16 -4
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -3
- data/vendor/faiss/faiss/IndexShards.cpp +7 -6
- data/vendor/faiss/faiss/MatrixStats.cpp +16 -8
- data/vendor/faiss/faiss/MetaIndexes.cpp +12 -6
- data/vendor/faiss/faiss/MetricType.h +5 -3
- data/vendor/faiss/faiss/clone_index.cpp +2 -4
- data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +6 -0
- data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +9 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +32 -10
- data/vendor/faiss/faiss/gpu/GpuIndex.h +88 -0
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +125 -0
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +39 -4
- data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +3 -3
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +1 -1
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +3 -2
- data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +41 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +6 -3
- data/vendor/faiss/faiss/impl/HNSW.cpp +34 -19
- data/vendor/faiss/faiss/impl/IDSelector.cpp +2 -1
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -3
- data/vendor/faiss/faiss/impl/NNDescent.cpp +17 -9
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +42 -21
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +6 -24
- data/vendor/faiss/faiss/impl/ResultHandler.h +56 -47
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +28 -15
- data/vendor/faiss/faiss/impl/index_read.cpp +36 -11
- data/vendor/faiss/faiss/impl/index_write.cpp +19 -6
- data/vendor/faiss/faiss/impl/io.cpp +9 -5
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +18 -11
- data/vendor/faiss/faiss/impl/mapped_io.cpp +4 -7
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +0 -1
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +0 -1
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +6 -6
- data/vendor/faiss/faiss/impl/zerocopy_io.cpp +1 -1
- data/vendor/faiss/faiss/impl/zerocopy_io.h +2 -2
- data/vendor/faiss/faiss/index_factory.cpp +49 -33
- data/vendor/faiss/faiss/index_factory.h +8 -2
- data/vendor/faiss/faiss/index_io.h +0 -3
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +2 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +12 -6
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +8 -4
- data/vendor/faiss/faiss/utils/Heap.cpp +15 -8
- data/vendor/faiss/faiss/utils/Heap.h +23 -12
- data/vendor/faiss/faiss/utils/distances.cpp +42 -21
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +2 -2
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +1 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +5 -3
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +27 -4
- data/vendor/faiss/faiss/utils/extra_distances.cpp +8 -4
- data/vendor/faiss/faiss/utils/hamming.cpp +20 -10
- data/vendor/faiss/faiss/utils/partitioning.cpp +8 -4
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +17 -9
- data/vendor/faiss/faiss/utils/rabitq_simd.h +539 -0
- data/vendor/faiss/faiss/utils/random.cpp +14 -7
- data/vendor/faiss/faiss/utils/utils.cpp +0 -3
- metadata +5 -2
@@ -79,6 +79,33 @@ struct ResultHandler {
|
|
79
79
|
virtual ~ResultHandler() {}
|
80
80
|
};
|
81
81
|
|
82
|
+
/*****************************************************************
|
83
|
+
* Common ancestor for top-k search results.
|
84
|
+
*****************************************************************/
|
85
|
+
|
86
|
+
template <class C, bool use_sel = false>
|
87
|
+
struct TopkBlockResultHandler : BlockResultHandler<C, use_sel> {
|
88
|
+
using T = typename C::T;
|
89
|
+
using TI = typename C::TI;
|
90
|
+
T* dis_tab;
|
91
|
+
TI* ids_tab;
|
92
|
+
|
93
|
+
int64_t k; // number of results to keep
|
94
|
+
|
95
|
+
TopkBlockResultHandler(
|
96
|
+
size_t nq,
|
97
|
+
T* dis_tab,
|
98
|
+
TI* ids_tab,
|
99
|
+
size_t k,
|
100
|
+
const IDSelector* sel = nullptr)
|
101
|
+
: BlockResultHandler<C, use_sel>(nq, sel),
|
102
|
+
dis_tab(dis_tab),
|
103
|
+
ids_tab(ids_tab),
|
104
|
+
k(k) {}
|
105
|
+
|
106
|
+
~TopkBlockResultHandler() {}
|
107
|
+
};
|
108
|
+
|
82
109
|
/*****************************************************************
|
83
110
|
* Single best result handler.
|
84
111
|
* Tracks the only best result, thus avoiding storing
|
@@ -86,25 +113,19 @@ struct ResultHandler {
|
|
86
113
|
*****************************************************************/
|
87
114
|
|
88
115
|
template <class C, bool use_sel = false>
|
89
|
-
struct Top1BlockResultHandler :
|
116
|
+
struct Top1BlockResultHandler : TopkBlockResultHandler<C, use_sel> {
|
90
117
|
using T = typename C::T;
|
91
118
|
using TI = typename C::TI;
|
92
119
|
using BlockResultHandler<C, use_sel>::i0;
|
93
120
|
using BlockResultHandler<C, use_sel>::i1;
|
94
121
|
|
95
|
-
// contains exactly nq elements
|
96
|
-
T* dis_tab;
|
97
|
-
// contains exactly nq elements
|
98
|
-
TI* ids_tab;
|
99
|
-
|
100
122
|
Top1BlockResultHandler(
|
101
123
|
size_t nq,
|
102
124
|
T* dis_tab,
|
103
125
|
TI* ids_tab,
|
104
126
|
const IDSelector* sel = nullptr)
|
105
|
-
:
|
106
|
-
|
107
|
-
ids_tab(ids_tab) {}
|
127
|
+
: TopkBlockResultHandler<C, use_sel>(nq, dis_tab, ids_tab, 1, sel) {
|
128
|
+
}
|
108
129
|
|
109
130
|
struct SingleResultHandler : ResultHandler<C> {
|
110
131
|
Top1BlockResultHandler& hr;
|
@@ -184,28 +205,21 @@ struct Top1BlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
184
205
|
*****************************************************************/
|
185
206
|
|
186
207
|
template <class C, bool use_sel = false>
|
187
|
-
struct HeapBlockResultHandler :
|
208
|
+
struct HeapBlockResultHandler : TopkBlockResultHandler<C, use_sel> {
|
188
209
|
using T = typename C::T;
|
189
210
|
using TI = typename C::TI;
|
190
211
|
using BlockResultHandler<C, use_sel>::i0;
|
191
212
|
using BlockResultHandler<C, use_sel>::i1;
|
192
|
-
|
193
|
-
T* heap_dis_tab;
|
194
|
-
TI* heap_ids_tab;
|
195
|
-
|
196
|
-
int64_t k; // number of results to keep
|
213
|
+
using TopkBlockResultHandler<C, use_sel>::k;
|
197
214
|
|
198
215
|
HeapBlockResultHandler(
|
199
216
|
size_t nq,
|
200
|
-
T*
|
201
|
-
TI*
|
217
|
+
T* dis_tab,
|
218
|
+
TI* ids_tab,
|
202
219
|
size_t k,
|
203
220
|
const IDSelector* sel = nullptr)
|
204
|
-
:
|
205
|
-
|
206
|
-
heap_ids_tab(heap_ids_tab),
|
207
|
-
k(k) {}
|
208
|
-
|
221
|
+
: TopkBlockResultHandler<C, use_sel>(nq, dis_tab, ids_tab, k, sel) {
|
222
|
+
}
|
209
223
|
/******************************************************
|
210
224
|
* API for 1 result at a time (each SingleResultHandler is
|
211
225
|
* called from 1 thread)
|
@@ -224,8 +238,8 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
224
238
|
|
225
239
|
/// begin results for query # i
|
226
240
|
void begin(size_t i) {
|
227
|
-
heap_dis = hr.
|
228
|
-
heap_ids = hr.
|
241
|
+
heap_dis = hr.dis_tab + i * k;
|
242
|
+
heap_ids = hr.ids_tab + i * k;
|
229
243
|
heap_heapify<C>(k, heap_dis, heap_ids);
|
230
244
|
threshold = heap_dis[0];
|
231
245
|
}
|
@@ -255,7 +269,8 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
255
269
|
this->i0 = i0_2;
|
256
270
|
this->i1 = i1_2;
|
257
271
|
for (size_t i = i0; i < i1; i++) {
|
258
|
-
heap_heapify<C>(
|
272
|
+
heap_heapify<C>(
|
273
|
+
k, this->dis_tab + i * this->k, this->ids_tab + i * k);
|
259
274
|
}
|
260
275
|
}
|
261
276
|
|
@@ -263,8 +278,8 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
263
278
|
void add_results(size_t j0, size_t j1, const T* dis_tab) final {
|
264
279
|
#pragma omp parallel for
|
265
280
|
for (int64_t i = i0; i < i1; i++) {
|
266
|
-
T* heap_dis =
|
267
|
-
TI* heap_ids =
|
281
|
+
T* heap_dis = this->dis_tab + i * k;
|
282
|
+
TI* heap_ids = this->ids_tab + i * k;
|
268
283
|
const T* dis_tab_i = dis_tab + (j1 - j0) * (i - i0) - j0;
|
269
284
|
T thresh = heap_dis[0];
|
270
285
|
for (size_t j = j0; j < j1; j++) {
|
@@ -281,7 +296,7 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
281
296
|
void end_multiple() final {
|
282
297
|
// maybe parallel for
|
283
298
|
for (size_t i = i0; i < i1; i++) {
|
284
|
-
heap_reorder<C>(k,
|
299
|
+
heap_reorder<C>(k, this->dis_tab + i * k, this->ids_tab + i * k);
|
285
300
|
}
|
286
301
|
}
|
287
302
|
};
|
@@ -290,9 +305,9 @@ struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
290
305
|
* Reservoir result handler
|
291
306
|
*
|
292
307
|
* A reservoir is a result array of size capacity > n (number of requested
|
293
|
-
* results) all results below a threshold are stored in an arbitrary order.
|
294
|
-
* the capacity is reached, a new threshold is chosen by partitionning
|
295
|
-
* distance array.
|
308
|
+
* results) all results below a threshold are stored in an arbitrary order.
|
309
|
+
*When the capacity is reached, a new threshold is chosen by partitionning
|
310
|
+
*the distance array.
|
296
311
|
*****************************************************************/
|
297
312
|
|
298
313
|
/// Reservoir for a single query
|
@@ -367,28 +382,21 @@ struct ReservoirTopN : ResultHandler<C> {
|
|
367
382
|
};
|
368
383
|
|
369
384
|
template <class C, bool use_sel = false>
|
370
|
-
struct ReservoirBlockResultHandler :
|
385
|
+
struct ReservoirBlockResultHandler : TopkBlockResultHandler<C, use_sel> {
|
371
386
|
using T = typename C::T;
|
372
387
|
using TI = typename C::TI;
|
373
388
|
using BlockResultHandler<C, use_sel>::i0;
|
374
389
|
using BlockResultHandler<C, use_sel>::i1;
|
375
390
|
|
376
|
-
T* heap_dis_tab;
|
377
|
-
TI* heap_ids_tab;
|
378
|
-
|
379
|
-
int64_t k; // number of results to keep
|
380
391
|
size_t capacity; // capacity of the reservoirs
|
381
392
|
|
382
393
|
ReservoirBlockResultHandler(
|
383
394
|
size_t nq,
|
384
|
-
T*
|
385
|
-
TI*
|
395
|
+
T* dis_tab,
|
396
|
+
TI* ids_tab,
|
386
397
|
size_t k,
|
387
398
|
const IDSelector* sel = nullptr)
|
388
|
-
:
|
389
|
-
heap_dis_tab(heap_dis_tab),
|
390
|
-
heap_ids_tab(heap_ids_tab),
|
391
|
-
k(k) {
|
399
|
+
: TopkBlockResultHandler<C, use_sel>(nq, dis_tab, ids_tab, k, sel) {
|
392
400
|
// double then round up to multiple of 16 (for SIMD alignment)
|
393
401
|
capacity = (2 * k + 15) & ~15;
|
394
402
|
}
|
@@ -423,8 +431,8 @@ struct ReservoirBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
423
431
|
|
424
432
|
/// series of results for query qno is done
|
425
433
|
void end() {
|
426
|
-
T* heap_dis = hr.
|
427
|
-
TI* heap_ids = hr.
|
434
|
+
T* heap_dis = hr.dis_tab + qno * hr.k;
|
435
|
+
TI* heap_ids = hr.ids_tab + qno * hr.k;
|
428
436
|
this->to_result(heap_dis, heap_ids);
|
429
437
|
}
|
430
438
|
};
|
@@ -446,7 +454,7 @@ struct ReservoirBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
446
454
|
reservoirs.clear();
|
447
455
|
for (size_t i = i0_2; i < i1_2; i++) {
|
448
456
|
reservoirs.emplace_back(
|
449
|
-
k,
|
457
|
+
this->k,
|
450
458
|
capacity,
|
451
459
|
reservoir_dis.data() + (i - i0_2) * capacity,
|
452
460
|
reservoir_ids.data() + (i - i0_2) * capacity);
|
@@ -471,7 +479,7 @@ struct ReservoirBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
471
479
|
// maybe parallel for
|
472
480
|
for (size_t i = i0; i < i1; i++) {
|
473
481
|
reservoirs[i - i0].to_result(
|
474
|
-
|
482
|
+
this->dis_tab + i * this->k, this->ids_tab + i * this->k);
|
475
483
|
}
|
476
484
|
}
|
477
485
|
};
|
@@ -535,7 +543,8 @@ struct RangeSearchBlockResultHandler : BlockResultHandler<C, use_sel> {
|
|
535
543
|
// finalize the partial result
|
536
544
|
pres.finalize();
|
537
545
|
} catch ([[maybe_unused]] const faiss::FaissException& e) {
|
538
|
-
// Do nothing if allocation fails in finalizing partial
|
546
|
+
// Do nothing if allocation fails in finalizing partial
|
547
|
+
// results.
|
539
548
|
#ifndef NDEBUG
|
540
549
|
std::cerr << e.what() << std::endl;
|
541
550
|
#endif
|
@@ -13,7 +13,6 @@
|
|
13
13
|
#include <cstdio>
|
14
14
|
|
15
15
|
#include <faiss/impl/platform_macros.h>
|
16
|
-
#include <omp.h>
|
17
16
|
|
18
17
|
#ifdef __SSE__
|
19
18
|
#include <immintrin.h>
|
@@ -985,10 +984,12 @@ void train_Uniform(
|
|
985
984
|
vmin = HUGE_VAL;
|
986
985
|
vmax = -HUGE_VAL;
|
987
986
|
for (size_t i = 0; i < n; i++) {
|
988
|
-
if (x[i] < vmin)
|
987
|
+
if (x[i] < vmin) {
|
989
988
|
vmin = x[i];
|
990
|
-
|
989
|
+
}
|
990
|
+
if (x[i] > vmax) {
|
991
991
|
vmax = x[i];
|
992
|
+
}
|
992
993
|
}
|
993
994
|
float vexp = (vmax - vmin) * rs_arg;
|
994
995
|
vmin -= vexp;
|
@@ -1011,10 +1012,12 @@ void train_Uniform(
|
|
1011
1012
|
// TODO just do a quickselect
|
1012
1013
|
std::sort(x_copy.begin(), x_copy.end());
|
1013
1014
|
int o = int(rs_arg * n);
|
1014
|
-
if (o < 0)
|
1015
|
+
if (o < 0) {
|
1015
1016
|
o = 0;
|
1016
|
-
|
1017
|
+
}
|
1018
|
+
if (o > n - o) {
|
1017
1019
|
o = n / 2;
|
1020
|
+
}
|
1018
1021
|
vmin = x_copy[o];
|
1019
1022
|
vmax = x_copy[n - 1 - o];
|
1020
1023
|
|
@@ -1024,10 +1027,12 @@ void train_Uniform(
|
|
1024
1027
|
{
|
1025
1028
|
vmin = HUGE_VAL, vmax = -HUGE_VAL;
|
1026
1029
|
for (size_t i = 0; i < n; i++) {
|
1027
|
-
if (x[i] < vmin)
|
1030
|
+
if (x[i] < vmin) {
|
1028
1031
|
vmin = x[i];
|
1029
|
-
|
1032
|
+
}
|
1033
|
+
if (x[i] > vmax) {
|
1030
1034
|
vmax = x[i];
|
1035
|
+
}
|
1031
1036
|
sx += x[i];
|
1032
1037
|
}
|
1033
1038
|
b = vmin;
|
@@ -1043,10 +1048,12 @@ void train_Uniform(
|
|
1043
1048
|
for (idx_t i = 0; i < n; i++) {
|
1044
1049
|
float xi = x[i];
|
1045
1050
|
float ni = floor((xi - b) / a + 0.5);
|
1046
|
-
if (ni < 0)
|
1051
|
+
if (ni < 0) {
|
1047
1052
|
ni = 0;
|
1048
|
-
|
1053
|
+
}
|
1054
|
+
if (ni >= k) {
|
1049
1055
|
ni = k - 1;
|
1056
|
+
}
|
1050
1057
|
err1 += sqr(xi - (ni * a + b));
|
1051
1058
|
sn += ni;
|
1052
1059
|
sn2 += ni * ni;
|
@@ -1055,8 +1062,9 @@ void train_Uniform(
|
|
1055
1062
|
|
1056
1063
|
if (err1 == last_err) {
|
1057
1064
|
iter_last_err++;
|
1058
|
-
if (iter_last_err == 16)
|
1065
|
+
if (iter_last_err == 16) {
|
1059
1066
|
break;
|
1067
|
+
}
|
1060
1068
|
} else {
|
1061
1069
|
last_err = err1;
|
1062
1070
|
iter_last_err = 0;
|
@@ -1071,8 +1079,9 @@ void train_Uniform(
|
|
1071
1079
|
fflush(stdout);
|
1072
1080
|
}
|
1073
1081
|
}
|
1074
|
-
if (verbose)
|
1082
|
+
if (verbose) {
|
1075
1083
|
printf("\n");
|
1084
|
+
}
|
1076
1085
|
|
1077
1086
|
vmin = b;
|
1078
1087
|
vmax = b + a * (k - 1);
|
@@ -1100,10 +1109,12 @@ void train_NonUniform(
|
|
1100
1109
|
for (size_t i = 1; i < n; i++) {
|
1101
1110
|
const float* xi = x + i * d;
|
1102
1111
|
for (size_t j = 0; j < d; j++) {
|
1103
|
-
if (xi[j] < vmin[j])
|
1112
|
+
if (xi[j] < vmin[j]) {
|
1104
1113
|
vmin[j] = xi[j];
|
1105
|
-
|
1114
|
+
}
|
1115
|
+
if (xi[j] > vmax[j]) {
|
1106
1116
|
vmax[j] = xi[j];
|
1117
|
+
}
|
1107
1118
|
}
|
1108
1119
|
}
|
1109
1120
|
float* vdiff = vmax;
|
@@ -2066,16 +2077,18 @@ void ScalarQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
|
|
2066
2077
|
|
2067
2078
|
memset(codes, 0, code_size * n);
|
2068
2079
|
#pragma omp parallel for
|
2069
|
-
for (int64_t i = 0; i < n; i++)
|
2080
|
+
for (int64_t i = 0; i < n; i++) {
|
2070
2081
|
squant->encode_vector(x + i * d, codes + i * code_size);
|
2082
|
+
}
|
2071
2083
|
}
|
2072
2084
|
|
2073
2085
|
void ScalarQuantizer::decode(const uint8_t* codes, float* x, size_t n) const {
|
2074
2086
|
std::unique_ptr<SQuantizer> squant(select_quantizer());
|
2075
2087
|
|
2076
2088
|
#pragma omp parallel for
|
2077
|
-
for (int64_t i = 0; i < n; i++)
|
2089
|
+
for (int64_t i = 0; i < n; i++) {
|
2078
2090
|
squant->decode_vector(codes + i * code_size, x + i * d);
|
2091
|
+
}
|
2079
2092
|
}
|
2080
2093
|
|
2081
2094
|
SQDistanceComputer* ScalarQuantizer::get_distance_computer(
|
@@ -16,7 +16,6 @@
|
|
16
16
|
|
17
17
|
#include <faiss/impl/FaissAssert.h>
|
18
18
|
#include <faiss/impl/io.h>
|
19
|
-
#include <faiss/impl/io_macros.h>
|
20
19
|
#include <faiss/utils/hamming.h>
|
21
20
|
|
22
21
|
#include <faiss/invlists/InvertedListsIOHook.h>
|
@@ -1100,24 +1099,37 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
1100
1099
|
idx = idxp;
|
1101
1100
|
} else if (
|
1102
1101
|
h == fourcc("IHNf") || h == fourcc("IHNp") || h == fourcc("IHNs") ||
|
1103
|
-
h == fourcc("IHN2") || h == fourcc("IHNc")) {
|
1102
|
+
h == fourcc("IHN2") || h == fourcc("IHNc") || h == fourcc("IHc2")) {
|
1104
1103
|
IndexHNSW* idxhnsw = nullptr;
|
1105
|
-
if (h == fourcc("IHNf"))
|
1104
|
+
if (h == fourcc("IHNf")) {
|
1106
1105
|
idxhnsw = new IndexHNSWFlat();
|
1107
|
-
|
1106
|
+
}
|
1107
|
+
if (h == fourcc("IHNp")) {
|
1108
1108
|
idxhnsw = new IndexHNSWPQ();
|
1109
|
-
|
1109
|
+
}
|
1110
|
+
if (h == fourcc("IHNs")) {
|
1110
1111
|
idxhnsw = new IndexHNSWSQ();
|
1111
|
-
|
1112
|
+
}
|
1113
|
+
if (h == fourcc("IHN2")) {
|
1112
1114
|
idxhnsw = new IndexHNSW2Level();
|
1113
|
-
|
1115
|
+
}
|
1116
|
+
if (h == fourcc("IHNc")) {
|
1117
|
+
idxhnsw = new IndexHNSWCagra();
|
1118
|
+
}
|
1119
|
+
if (h == fourcc("IHc2")) {
|
1114
1120
|
idxhnsw = new IndexHNSWCagra();
|
1121
|
+
}
|
1115
1122
|
read_index_header(idxhnsw, f);
|
1116
|
-
if (h == fourcc("IHNc")) {
|
1123
|
+
if (h == fourcc("IHNc") || h == fourcc("IHc2")) {
|
1117
1124
|
READ1(idxhnsw->keep_max_size_level0);
|
1118
1125
|
auto idx_hnsw_cagra = dynamic_cast<IndexHNSWCagra*>(idxhnsw);
|
1119
1126
|
READ1(idx_hnsw_cagra->base_level_only);
|
1120
1127
|
READ1(idx_hnsw_cagra->num_base_level_search_entrypoints);
|
1128
|
+
if (h == fourcc("IHc2")) {
|
1129
|
+
READ1(idx_hnsw_cagra->numeric_type_);
|
1130
|
+
} else { // cagra before numeric_type_ was introduced
|
1131
|
+
idx_hnsw_cagra->set_numeric_type(faiss::Float32);
|
1132
|
+
}
|
1121
1133
|
}
|
1122
1134
|
read_HNSW(&idxhnsw->hnsw, f);
|
1123
1135
|
idxhnsw->storage = read_index(f, io_flags);
|
@@ -1129,12 +1141,15 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
1129
1141
|
} else if (
|
1130
1142
|
h == fourcc("INSf") || h == fourcc("INSp") || h == fourcc("INSs")) {
|
1131
1143
|
IndexNSG* idxnsg;
|
1132
|
-
if (h == fourcc("INSf"))
|
1144
|
+
if (h == fourcc("INSf")) {
|
1133
1145
|
idxnsg = new IndexNSGFlat();
|
1134
|
-
|
1146
|
+
}
|
1147
|
+
if (h == fourcc("INSp")) {
|
1135
1148
|
idxnsg = new IndexNSGPQ();
|
1136
|
-
|
1149
|
+
}
|
1150
|
+
if (h == fourcc("INSs")) {
|
1137
1151
|
idxnsg = new IndexNSGSQ();
|
1152
|
+
}
|
1138
1153
|
read_index_header(idxnsg, f);
|
1139
1154
|
READ1(idxnsg->GK);
|
1140
1155
|
READ1(idxnsg->build_type);
|
@@ -1384,6 +1399,16 @@ IndexBinary* read_index_binary(IOReader* f, int io_flags) {
|
|
1384
1399
|
idxhnsw->storage = read_index_binary(f, io_flags);
|
1385
1400
|
idxhnsw->own_fields = true;
|
1386
1401
|
idx = idxhnsw;
|
1402
|
+
} else if (h == fourcc("IBHc")) {
|
1403
|
+
IndexBinaryHNSWCagra* idxhnsw = new IndexBinaryHNSWCagra();
|
1404
|
+
read_index_binary_header(idxhnsw, f);
|
1405
|
+
READ1(idxhnsw->keep_max_size_level0);
|
1406
|
+
READ1(idxhnsw->base_level_only);
|
1407
|
+
READ1(idxhnsw->num_base_level_search_entrypoints);
|
1408
|
+
read_HNSW(&idxhnsw->hnsw, f);
|
1409
|
+
idxhnsw->storage = read_index_binary(f, io_flags);
|
1410
|
+
idxhnsw->own_fields = true;
|
1411
|
+
idx = idxhnsw;
|
1387
1412
|
} else if (h == fourcc("IBMp") || h == fourcc("IBM2")) {
|
1388
1413
|
bool is_map2 = h == fourcc("IBM2");
|
1389
1414
|
IndexBinaryIDMap* idxmap =
|
@@ -16,7 +16,6 @@
|
|
16
16
|
#include <faiss/invlists/InvertedListsIOHook.h>
|
17
17
|
|
18
18
|
#include <faiss/impl/FaissAssert.h>
|
19
|
-
#include <faiss/impl/io_macros.h>
|
20
19
|
#include <faiss/utils/hamming.h>
|
21
20
|
|
22
21
|
#include <faiss/Index2Layer.h>
|
@@ -255,8 +254,9 @@ void write_InvertedLists(const InvertedLists* ils, IOWriter* f) {
|
|
255
254
|
// here we store either as a full or a sparse data buffer
|
256
255
|
size_t n_non0 = 0;
|
257
256
|
for (size_t i = 0; i < ails->nlist; i++) {
|
258
|
-
if (ails->ids[i].size() > 0)
|
257
|
+
if (ails->ids[i].size() > 0) {
|
259
258
|
n_non0++;
|
259
|
+
}
|
260
260
|
}
|
261
261
|
if (n_non0 > ails->nlist / 2) {
|
262
262
|
uint32_t list_type = fourcc("full");
|
@@ -739,8 +739,9 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
739
739
|
write_index_header(ixpt, f);
|
740
740
|
int nt = ixpt->chain.size();
|
741
741
|
WRITE1(nt);
|
742
|
-
for (int i = 0; i < nt; i++)
|
742
|
+
for (int i = 0; i < nt; i++) {
|
743
743
|
write_VectorTransform(ixpt->chain[i], f);
|
744
|
+
}
|
744
745
|
write_index(ixpt->index, f);
|
745
746
|
} else if (
|
746
747
|
const MultiIndexQuantizer* imiq =
|
@@ -771,16 +772,17 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
771
772
|
: dynamic_cast<const IndexHNSWPQ*>(idx) ? fourcc("IHNp")
|
772
773
|
: dynamic_cast<const IndexHNSWSQ*>(idx) ? fourcc("IHNs")
|
773
774
|
: dynamic_cast<const IndexHNSW2Level*>(idx) ? fourcc("IHN2")
|
774
|
-
: dynamic_cast<const IndexHNSWCagra*>(idx) ? fourcc("
|
775
|
+
: dynamic_cast<const IndexHNSWCagra*>(idx) ? fourcc("IHc2")
|
775
776
|
: 0;
|
776
777
|
FAISS_THROW_IF_NOT(h != 0);
|
777
778
|
WRITE1(h);
|
778
779
|
write_index_header(idxhnsw, f);
|
779
|
-
if (h == fourcc("
|
780
|
+
if (h == fourcc("IHc2")) {
|
780
781
|
WRITE1(idxhnsw->keep_max_size_level0);
|
781
782
|
auto idx_hnsw_cagra = dynamic_cast<const IndexHNSWCagra*>(idxhnsw);
|
782
783
|
WRITE1(idx_hnsw_cagra->base_level_only);
|
783
784
|
WRITE1(idx_hnsw_cagra->num_base_level_search_entrypoints);
|
785
|
+
WRITE1(idx_hnsw_cagra->numeric_type_);
|
784
786
|
}
|
785
787
|
write_HNSW(&idxhnsw->hnsw, f);
|
786
788
|
if (io_flags & IO_FLAG_SKIP_STORAGE) {
|
@@ -1004,9 +1006,20 @@ void write_index_binary(const IndexBinary* idx, IOWriter* f) {
|
|
1004
1006
|
} else if (
|
1005
1007
|
const IndexBinaryHNSW* idxhnsw =
|
1006
1008
|
dynamic_cast<const IndexBinaryHNSW*>(idx)) {
|
1007
|
-
|
1009
|
+
// Determine which type of binary HNSW index this is
|
1010
|
+
uint32_t h = dynamic_cast<const IndexBinaryHNSWCagra*>(idx)
|
1011
|
+
? fourcc("IBHc")
|
1012
|
+
: fourcc("IBHf");
|
1008
1013
|
WRITE1(h);
|
1009
1014
|
write_index_binary_header(idxhnsw, f);
|
1015
|
+
|
1016
|
+
if (h == fourcc("IBHc")) {
|
1017
|
+
auto idxcagra = dynamic_cast<const IndexBinaryHNSWCagra*>(idxhnsw);
|
1018
|
+
WRITE1(idxcagra->keep_max_size_level0);
|
1019
|
+
WRITE1(idxcagra->base_level_only);
|
1020
|
+
WRITE1(idxcagra->num_base_level_search_entrypoints);
|
1021
|
+
}
|
1022
|
+
|
1010
1023
|
write_HNSW(&idxhnsw->hnsw, f);
|
1011
1024
|
write_index_binary(idxhnsw->storage, f);
|
1012
1025
|
} else if (
|
@@ -43,11 +43,13 @@ size_t VectorIOWriter::operator()(const void* ptr, size_t size, size_t nitems) {
|
|
43
43
|
}
|
44
44
|
|
45
45
|
size_t VectorIOReader::operator()(void* ptr, size_t size, size_t nitems) {
|
46
|
-
if (rp >= data.size())
|
46
|
+
if (rp >= data.size()) {
|
47
47
|
return 0;
|
48
|
+
}
|
48
49
|
size_t nremain = (data.size() - rp) / size;
|
49
|
-
if (nremain < nitems)
|
50
|
+
if (nremain < nitems) {
|
50
51
|
nitems = nremain;
|
52
|
+
}
|
51
53
|
if (size * nitems > 0) {
|
52
54
|
memcpy(ptr, &data[rp], size * nitems);
|
53
55
|
rp += size * nitems;
|
@@ -143,8 +145,9 @@ BufferedIOReader::BufferedIOReader(IOReader* reader, size_t bsz)
|
|
143
145
|
|
144
146
|
size_t BufferedIOReader::operator()(void* ptr, size_t unitsize, size_t nitems) {
|
145
147
|
size_t size = unitsize * nitems;
|
146
|
-
if (size == 0)
|
148
|
+
if (size == 0) {
|
147
149
|
return 0;
|
150
|
+
}
|
148
151
|
char* dst = (char*)ptr;
|
149
152
|
size_t nb;
|
150
153
|
|
@@ -189,8 +192,9 @@ size_t BufferedIOWriter::operator()(
|
|
189
192
|
size_t unitsize,
|
190
193
|
size_t nitems) {
|
191
194
|
size_t size = unitsize * nitems;
|
192
|
-
if (size == 0)
|
195
|
+
if (size == 0) {
|
193
196
|
return 0;
|
197
|
+
}
|
194
198
|
const char* src = (const char*)ptr;
|
195
199
|
size_t nb;
|
196
200
|
|
@@ -260,7 +264,7 @@ std::string fourcc_inv(uint32_t x) {
|
|
260
264
|
std::string fourcc_inv_printable(uint32_t x) {
|
261
265
|
char cstr[5];
|
262
266
|
fourcc_inv(x, cstr);
|
263
|
-
std::string str
|
267
|
+
std::string str;
|
264
268
|
for (int i = 0; i < 4; i++) {
|
265
269
|
uint8_t c = cstr[i];
|
266
270
|
if (32 <= c && c < 127) {
|
@@ -18,7 +18,6 @@
|
|
18
18
|
#include <queue>
|
19
19
|
#include <unordered_set>
|
20
20
|
|
21
|
-
#include <faiss/impl/platform_macros.h>
|
22
21
|
#include <faiss/utils/distances.h>
|
23
22
|
|
24
23
|
namespace faiss {
|
@@ -53,8 +52,9 @@ struct Comb {
|
|
53
52
|
|
54
53
|
uint64_t operator()(int n, int p) const {
|
55
54
|
assert(n < nmax && p < nmax);
|
56
|
-
if (p > n)
|
55
|
+
if (p > n) {
|
57
56
|
return 0;
|
57
|
+
}
|
58
58
|
return tab[n * nmax + p];
|
59
59
|
}
|
60
60
|
};
|
@@ -66,8 +66,9 @@ point_list_t sum_of_sq(float total, int v, int n, float add = 0) {
|
|
66
66
|
if (total < 0) {
|
67
67
|
return point_list_t();
|
68
68
|
} else if (n == 1) {
|
69
|
-
while (sqr(v + add) > total)
|
69
|
+
while (sqr(v + add) > total) {
|
70
70
|
v--;
|
71
|
+
}
|
71
72
|
if (sqr(v + add) == total) {
|
72
73
|
return point_list_t(1, v + add);
|
73
74
|
} else {
|
@@ -118,8 +119,9 @@ uint64_t repeats_encode_64(
|
|
118
119
|
code_comb += comb(rank, occ + 1);
|
119
120
|
occ++;
|
120
121
|
coded |= uint64_t{1} << i;
|
121
|
-
if (occ == r->n)
|
122
|
+
if (occ == r->n) {
|
122
123
|
break;
|
124
|
+
}
|
123
125
|
}
|
124
126
|
rank++;
|
125
127
|
}
|
@@ -155,8 +157,9 @@ void repeats_decode_64(
|
|
155
157
|
decoded |= uint64_t{1} << i;
|
156
158
|
c[i] = r->val;
|
157
159
|
occ++;
|
158
|
-
if (occ == r->n)
|
160
|
+
if (occ == r->n) {
|
159
161
|
break;
|
162
|
+
}
|
160
163
|
next_rank = decode_comb_1(&code_comb, r->n - occ, next_rank);
|
161
164
|
}
|
162
165
|
}
|
@@ -210,8 +213,9 @@ uint64_t Repeats::encode(const float* c) const {
|
|
210
213
|
code_comb += comb(rank, occ + 1);
|
211
214
|
occ++;
|
212
215
|
coded[i] = true;
|
213
|
-
if (occ == r->n)
|
216
|
+
if (occ == r->n) {
|
214
217
|
break;
|
218
|
+
}
|
215
219
|
}
|
216
220
|
rank++;
|
217
221
|
}
|
@@ -247,8 +251,9 @@ void Repeats::decode(uint64_t code, float* c) const {
|
|
247
251
|
decoded[i] = true;
|
248
252
|
c[i] = r->val;
|
249
253
|
occ++;
|
250
|
-
if (occ == r->n)
|
254
|
+
if (occ == r->n) {
|
251
255
|
break;
|
256
|
+
}
|
252
257
|
next_rank =
|
253
258
|
decode_comb_1(&code_comb, r->n - occ, next_rank);
|
254
259
|
}
|
@@ -440,10 +445,11 @@ void ZnSphereCodec::decode(uint64_t code, float* c) const {
|
|
440
445
|
int i0 = 0, i1 = natom;
|
441
446
|
while (i0 + 1 < i1) {
|
442
447
|
int imed = (i0 + i1) / 2;
|
443
|
-
if (code_segments[imed].c0 <= code)
|
448
|
+
if (code_segments[imed].c0 <= code) {
|
444
449
|
i0 = imed;
|
445
|
-
else
|
450
|
+
} else {
|
446
451
|
i1 = imed;
|
452
|
+
}
|
447
453
|
}
|
448
454
|
const CodeSegment& cs = code_segments[i0];
|
449
455
|
code -= cs.c0;
|
@@ -592,10 +598,11 @@ void ZnSphereCodecRec::decode(uint64_t code, float* c) const {
|
|
592
598
|
&all_nv_cum[(ld * (r2 + 1) + r2sub) * (r2 + 1)];
|
593
599
|
while (i1 > i0 + 1) {
|
594
600
|
int imed = (i0 + i1) / 2;
|
595
|
-
if (cum[imed] <= codei)
|
601
|
+
if (cum[imed] <= codei) {
|
596
602
|
i0 = imed;
|
597
|
-
else
|
603
|
+
} else {
|
598
604
|
i1 = imed;
|
605
|
+
}
|
599
606
|
}
|
600
607
|
int r2a = i0, r2b = r2sub - i0;
|
601
608
|
codei -= cum[r2a];
|