faiss 0.2.0 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/LICENSE.txt +1 -1
- data/README.md +7 -7
- data/ext/faiss/extconf.rb +6 -3
- data/ext/faiss/numo.hpp +4 -4
- data/ext/faiss/utils.cpp +1 -1
- data/ext/faiss/utils.h +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +292 -291
- data/vendor/faiss/faiss/AutoTune.h +55 -56
- data/vendor/faiss/faiss/Clustering.cpp +365 -194
- data/vendor/faiss/faiss/Clustering.h +102 -35
- data/vendor/faiss/faiss/IVFlib.cpp +171 -195
- data/vendor/faiss/faiss/IVFlib.h +48 -51
- data/vendor/faiss/faiss/Index.cpp +85 -103
- data/vendor/faiss/faiss/Index.h +54 -48
- data/vendor/faiss/faiss/Index2Layer.cpp +126 -224
- data/vendor/faiss/faiss/Index2Layer.h +22 -36
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +407 -0
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +195 -0
- data/vendor/faiss/faiss/IndexBinary.cpp +45 -37
- data/vendor/faiss/faiss/IndexBinary.h +140 -132
- data/vendor/faiss/faiss/IndexBinaryFlat.cpp +73 -53
- data/vendor/faiss/faiss/IndexBinaryFlat.h +29 -24
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +46 -43
- data/vendor/faiss/faiss/IndexBinaryFromFloat.h +16 -15
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +215 -232
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +25 -24
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +182 -177
- data/vendor/faiss/faiss/IndexBinaryHash.h +41 -34
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +489 -461
- data/vendor/faiss/faiss/IndexBinaryIVF.h +97 -68
- data/vendor/faiss/faiss/IndexFlat.cpp +115 -176
- data/vendor/faiss/faiss/IndexFlat.h +42 -59
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +67 -0
- data/vendor/faiss/faiss/IndexFlatCodes.h +47 -0
- data/vendor/faiss/faiss/IndexHNSW.cpp +372 -348
- data/vendor/faiss/faiss/IndexHNSW.h +57 -41
- data/vendor/faiss/faiss/IndexIVF.cpp +545 -453
- data/vendor/faiss/faiss/IndexIVF.h +169 -118
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +316 -0
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +121 -0
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +247 -252
- data/vendor/faiss/faiss/IndexIVFFlat.h +48 -51
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +459 -517
- data/vendor/faiss/faiss/IndexIVFPQ.h +75 -67
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +406 -372
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +82 -57
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +104 -102
- data/vendor/faiss/faiss/IndexIVFPQR.h +33 -28
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +163 -150
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +38 -25
- data/vendor/faiss/faiss/IndexLSH.cpp +66 -113
- data/vendor/faiss/faiss/IndexLSH.h +20 -38
- data/vendor/faiss/faiss/IndexLattice.cpp +42 -56
- data/vendor/faiss/faiss/IndexLattice.h +11 -16
- data/vendor/faiss/faiss/IndexNNDescent.cpp +229 -0
- data/vendor/faiss/faiss/IndexNNDescent.h +72 -0
- data/vendor/faiss/faiss/IndexNSG.cpp +301 -0
- data/vendor/faiss/faiss/IndexNSG.h +85 -0
- data/vendor/faiss/faiss/IndexPQ.cpp +387 -495
- data/vendor/faiss/faiss/IndexPQ.h +64 -82
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +143 -170
- data/vendor/faiss/faiss/IndexPQFastScan.h +46 -32
- data/vendor/faiss/faiss/IndexPreTransform.cpp +120 -150
- data/vendor/faiss/faiss/IndexPreTransform.h +33 -36
- data/vendor/faiss/faiss/IndexRefine.cpp +139 -127
- data/vendor/faiss/faiss/IndexRefine.h +32 -23
- data/vendor/faiss/faiss/IndexReplicas.cpp +147 -153
- data/vendor/faiss/faiss/IndexReplicas.h +62 -56
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +111 -172
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +41 -59
- data/vendor/faiss/faiss/IndexShards.cpp +256 -240
- data/vendor/faiss/faiss/IndexShards.h +85 -73
- data/vendor/faiss/faiss/MatrixStats.cpp +112 -97
- data/vendor/faiss/faiss/MatrixStats.h +7 -10
- data/vendor/faiss/faiss/MetaIndexes.cpp +135 -157
- data/vendor/faiss/faiss/MetaIndexes.h +40 -34
- data/vendor/faiss/faiss/MetricType.h +7 -7
- data/vendor/faiss/faiss/VectorTransform.cpp +654 -475
- data/vendor/faiss/faiss/VectorTransform.h +64 -89
- data/vendor/faiss/faiss/clone_index.cpp +78 -73
- data/vendor/faiss/faiss/clone_index.h +4 -9
- data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +33 -38
- data/vendor/faiss/faiss/gpu/GpuAutoTune.h +11 -9
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +198 -171
- data/vendor/faiss/faiss/gpu/GpuCloner.h +53 -35
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.cpp +12 -14
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +27 -25
- data/vendor/faiss/faiss/gpu/GpuDistance.h +116 -112
- data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -2
- data/vendor/faiss/faiss/gpu/GpuIcmEncoder.h +60 -0
- data/vendor/faiss/faiss/gpu/GpuIndex.h +134 -137
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +76 -73
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +173 -162
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +67 -64
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +89 -86
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +150 -141
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +101 -103
- data/vendor/faiss/faiss/gpu/GpuIndicesOptions.h +17 -16
- data/vendor/faiss/faiss/gpu/GpuResources.cpp +116 -128
- data/vendor/faiss/faiss/gpu/GpuResources.h +182 -186
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +433 -422
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +131 -130
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +468 -456
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +25 -19
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +22 -20
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +9 -8
- data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +39 -44
- data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +16 -14
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +77 -71
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +109 -88
- data/vendor/faiss/faiss/gpu/perf/WriteIndex.cpp +75 -64
- data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +230 -215
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +80 -86
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +284 -277
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +416 -416
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +611 -517
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +166 -164
- data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +61 -53
- data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +274 -238
- data/vendor/faiss/faiss/gpu/test/TestUtils.h +73 -57
- data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +47 -50
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +79 -72
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +140 -146
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.h +69 -71
- data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +21 -16
- data/vendor/faiss/faiss/gpu/utils/Timer.cpp +25 -29
- data/vendor/faiss/faiss/gpu/utils/Timer.h +30 -29
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +503 -0
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +175 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +90 -120
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +81 -65
- data/vendor/faiss/faiss/impl/FaissAssert.h +73 -58
- data/vendor/faiss/faiss/impl/FaissException.cpp +56 -48
- data/vendor/faiss/faiss/impl/FaissException.h +41 -29
- data/vendor/faiss/faiss/impl/HNSW.cpp +606 -617
- data/vendor/faiss/faiss/impl/HNSW.h +179 -200
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +855 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +244 -0
- data/vendor/faiss/faiss/impl/NNDescent.cpp +487 -0
- data/vendor/faiss/faiss/impl/NNDescent.h +154 -0
- data/vendor/faiss/faiss/impl/NSG.cpp +679 -0
- data/vendor/faiss/faiss/impl/NSG.h +199 -0
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +484 -454
- data/vendor/faiss/faiss/impl/PolysemousTraining.h +52 -55
- data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +26 -47
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +469 -459
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +76 -87
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +758 -0
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +188 -0
- data/vendor/faiss/faiss/impl/ResultHandler.h +96 -132
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +647 -707
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +48 -46
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +129 -131
- data/vendor/faiss/faiss/impl/ThreadedIndex.h +61 -55
- data/vendor/faiss/faiss/impl/index_read.cpp +631 -480
- data/vendor/faiss/faiss/impl/index_write.cpp +547 -407
- data/vendor/faiss/faiss/impl/io.cpp +76 -95
- data/vendor/faiss/faiss/impl/io.h +31 -41
- data/vendor/faiss/faiss/impl/io_macros.h +60 -29
- data/vendor/faiss/faiss/impl/kmeans1d.cpp +301 -0
- data/vendor/faiss/faiss/impl/kmeans1d.h +48 -0
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +137 -186
- data/vendor/faiss/faiss/impl/lattice_Zn.h +40 -51
- data/vendor/faiss/faiss/impl/platform_macros.h +29 -8
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +77 -124
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +39 -48
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +41 -52
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +80 -117
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +109 -137
- data/vendor/faiss/faiss/index_factory.cpp +619 -397
- data/vendor/faiss/faiss/index_factory.h +8 -6
- data/vendor/faiss/faiss/index_io.h +23 -26
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +67 -75
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +22 -24
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +96 -112
- data/vendor/faiss/faiss/invlists/DirectMap.h +29 -33
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +307 -364
- data/vendor/faiss/faiss/invlists/InvertedLists.h +151 -151
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +29 -34
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +17 -18
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +257 -293
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +50 -45
- data/vendor/faiss/faiss/python/python_callbacks.cpp +23 -26
- data/vendor/faiss/faiss/python/python_callbacks.h +9 -16
- data/vendor/faiss/faiss/utils/AlignedTable.h +79 -44
- data/vendor/faiss/faiss/utils/Heap.cpp +40 -48
- data/vendor/faiss/faiss/utils/Heap.h +186 -209
- data/vendor/faiss/faiss/utils/WorkerThread.cpp +67 -76
- data/vendor/faiss/faiss/utils/WorkerThread.h +32 -33
- data/vendor/faiss/faiss/utils/distances.cpp +305 -312
- data/vendor/faiss/faiss/utils/distances.h +170 -122
- data/vendor/faiss/faiss/utils/distances_simd.cpp +498 -508
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +117 -0
- data/vendor/faiss/faiss/utils/extra_distances.cpp +113 -232
- data/vendor/faiss/faiss/utils/extra_distances.h +30 -29
- data/vendor/faiss/faiss/utils/hamming-inl.h +260 -209
- data/vendor/faiss/faiss/utils/hamming.cpp +375 -469
- data/vendor/faiss/faiss/utils/hamming.h +62 -85
- data/vendor/faiss/faiss/utils/ordered_key_value.h +16 -18
- data/vendor/faiss/faiss/utils/partitioning.cpp +393 -318
- data/vendor/faiss/faiss/utils/partitioning.h +26 -21
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +78 -66
- data/vendor/faiss/faiss/utils/quantize_lut.h +22 -20
- data/vendor/faiss/faiss/utils/random.cpp +39 -63
- data/vendor/faiss/faiss/utils/random.h +13 -16
- data/vendor/faiss/faiss/utils/simdlib.h +4 -2
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +88 -85
- data/vendor/faiss/faiss/utils/simdlib_emulated.h +226 -165
- data/vendor/faiss/faiss/utils/simdlib_neon.h +832 -0
- data/vendor/faiss/faiss/utils/utils.cpp +304 -287
- data/vendor/faiss/faiss/utils/utils.h +54 -49
- metadata +29 -4
|
@@ -9,11 +9,12 @@
|
|
|
9
9
|
|
|
10
10
|
#include <faiss/Index2Layer.h>
|
|
11
11
|
|
|
12
|
+
#include <faiss/impl/platform_macros.h>
|
|
13
|
+
#include <stdint.h>
|
|
14
|
+
#include <cassert>
|
|
12
15
|
#include <cinttypes>
|
|
13
16
|
#include <cmath>
|
|
14
17
|
#include <cstdio>
|
|
15
|
-
#include <cassert>
|
|
16
|
-
#include <stdint.h>
|
|
17
18
|
|
|
18
19
|
#ifdef __SSE3__
|
|
19
20
|
#include <immintrin.h>
|
|
@@ -23,39 +24,27 @@
|
|
|
23
24
|
|
|
24
25
|
#include <faiss/IndexIVFPQ.h>
|
|
25
26
|
|
|
26
|
-
#include <faiss/impl/FaissAssert.h>
|
|
27
|
-
#include <faiss/utils/utils.h>
|
|
28
|
-
#include <faiss/impl/AuxIndexStructures.h>
|
|
29
27
|
#include <faiss/IndexFlat.h>
|
|
28
|
+
#include <faiss/impl/AuxIndexStructures.h>
|
|
29
|
+
#include <faiss/impl/FaissAssert.h>
|
|
30
30
|
#include <faiss/utils/distances.h>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/*
|
|
34
|
-
#include <faiss/utils/Heap.h>
|
|
35
|
-
|
|
36
|
-
#include <faiss/Clustering.h>
|
|
37
|
-
|
|
38
|
-
#include <faiss/utils/hamming.h>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*/
|
|
42
|
-
|
|
31
|
+
#include <faiss/utils/utils.h>
|
|
43
32
|
|
|
44
33
|
namespace faiss {
|
|
45
34
|
|
|
46
|
-
|
|
47
35
|
/*************************************
|
|
48
36
|
* Index2Layer implementation
|
|
49
37
|
*************************************/
|
|
50
38
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
Index2Layer::Index2Layer(
|
|
40
|
+
Index* quantizer,
|
|
41
|
+
size_t nlist,
|
|
42
|
+
int M,
|
|
43
|
+
int nbit,
|
|
44
|
+
MetricType metric)
|
|
45
|
+
: IndexFlatCodes(0, quantizer->d, metric),
|
|
46
|
+
q1(quantizer, nlist),
|
|
47
|
+
pq(quantizer->d, M, nbit) {
|
|
59
48
|
is_trained = false;
|
|
60
49
|
for (int nbyte = 0; nbyte < 7; nbyte++) {
|
|
61
50
|
if ((1L << (8 * nbyte)) >= nlist) {
|
|
@@ -67,177 +56,94 @@ Index2Layer::Index2Layer (Index * quantizer, size_t nlist,
|
|
|
67
56
|
code_size = code_size_1 + code_size_2;
|
|
68
57
|
}
|
|
69
58
|
|
|
70
|
-
Index2Layer::Index2Layer
|
|
71
|
-
{
|
|
59
|
+
Index2Layer::Index2Layer() {
|
|
72
60
|
code_size = code_size_1 = code_size_2 = 0;
|
|
73
61
|
}
|
|
74
62
|
|
|
75
|
-
Index2Layer::~Index2Layer
|
|
76
|
-
{}
|
|
63
|
+
Index2Layer::~Index2Layer() {}
|
|
77
64
|
|
|
78
|
-
void Index2Layer::train(idx_t n, const float* x)
|
|
79
|
-
{
|
|
65
|
+
void Index2Layer::train(idx_t n, const float* x) {
|
|
80
66
|
if (verbose) {
|
|
81
|
-
printf
|
|
82
|
-
n, d);
|
|
67
|
+
printf("training level-1 quantizer %" PRId64 " vectors in %dD\n", n, d);
|
|
83
68
|
}
|
|
84
69
|
|
|
85
|
-
q1.train_q1
|
|
70
|
+
q1.train_q1(n, x, verbose, metric_type);
|
|
86
71
|
|
|
87
72
|
if (verbose) {
|
|
88
73
|
printf("computing residuals\n");
|
|
89
74
|
}
|
|
90
75
|
|
|
91
|
-
const float
|
|
76
|
+
const float* x_in = x;
|
|
92
77
|
|
|
93
|
-
x = fvecs_maybe_subsample
|
|
94
|
-
|
|
95
|
-
|
|
78
|
+
x = fvecs_maybe_subsample(
|
|
79
|
+
d,
|
|
80
|
+
(size_t*)&n,
|
|
81
|
+
pq.cp.max_points_per_centroid * pq.ksub,
|
|
82
|
+
x,
|
|
83
|
+
verbose,
|
|
84
|
+
pq.cp.seed);
|
|
96
85
|
|
|
97
|
-
ScopeDeleter<float> del_x
|
|
86
|
+
ScopeDeleter<float> del_x(x_in == x ? nullptr : x);
|
|
98
87
|
|
|
99
88
|
std::vector<idx_t> assign(n); // assignement to coarse centroids
|
|
100
|
-
q1.quantizer->assign
|
|
89
|
+
q1.quantizer->assign(n, x, assign.data());
|
|
101
90
|
std::vector<float> residuals(n * d);
|
|
102
91
|
for (idx_t i = 0; i < n; i++) {
|
|
103
|
-
q1.quantizer->compute_residual
|
|
104
|
-
|
|
92
|
+
q1.quantizer->compute_residual(
|
|
93
|
+
x + i * d, residuals.data() + i * d, assign[i]);
|
|
105
94
|
}
|
|
106
95
|
|
|
107
96
|
if (verbose)
|
|
108
|
-
printf
|
|
109
|
-
|
|
97
|
+
printf("training %zdx%zd product quantizer on %" PRId64
|
|
98
|
+
" vectors in %dD\n",
|
|
99
|
+
pq.M,
|
|
100
|
+
pq.ksub,
|
|
101
|
+
n,
|
|
102
|
+
d);
|
|
110
103
|
pq.verbose = verbose;
|
|
111
|
-
pq.train
|
|
104
|
+
pq.train(n, residuals.data());
|
|
112
105
|
|
|
113
106
|
is_trained = true;
|
|
114
107
|
}
|
|
115
108
|
|
|
116
|
-
void Index2Layer::add(idx_t n, const float* x)
|
|
117
|
-
{
|
|
118
|
-
idx_t bs = 32768;
|
|
119
|
-
if (n > bs) {
|
|
120
|
-
for (idx_t i0 = 0; i0 < n; i0 += bs) {
|
|
121
|
-
idx_t i1 = std::min(i0 + bs, n);
|
|
122
|
-
if (verbose) {
|
|
123
|
-
printf("Index2Layer::add: adding %" PRId64 ":%" PRId64 " / %" PRId64 "\n",
|
|
124
|
-
i0, i1, n);
|
|
125
|
-
}
|
|
126
|
-
add (i1 - i0, x + i0 * d);
|
|
127
|
-
}
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
std::vector<idx_t> codes1 (n);
|
|
132
|
-
q1.quantizer->assign (n, x, codes1.data());
|
|
133
|
-
std::vector<float> residuals(n * d);
|
|
134
|
-
for (idx_t i = 0; i < n; i++) {
|
|
135
|
-
q1.quantizer->compute_residual (
|
|
136
|
-
x + i * d, residuals.data() + i * d, codes1[i]);
|
|
137
|
-
}
|
|
138
|
-
std::vector<uint8_t> codes2 (n * code_size_2);
|
|
139
|
-
|
|
140
|
-
pq.compute_codes (residuals.data(), codes2.data(), n);
|
|
141
|
-
|
|
142
|
-
codes.resize ((ntotal + n) * code_size);
|
|
143
|
-
uint8_t *wp = &codes[ntotal * code_size];
|
|
144
|
-
|
|
145
|
-
{
|
|
146
|
-
int i = 0x11223344;
|
|
147
|
-
const char *ip = (char*)&i;
|
|
148
|
-
FAISS_THROW_IF_NOT_MSG (ip[0] == 0x44,
|
|
149
|
-
"works only on a little-endian CPU");
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// copy to output table
|
|
153
|
-
for (idx_t i = 0; i < n; i++) {
|
|
154
|
-
memcpy (wp, &codes1[i], code_size_1);
|
|
155
|
-
wp += code_size_1;
|
|
156
|
-
memcpy (wp, &codes2[i * code_size_2], code_size_2);
|
|
157
|
-
wp += code_size_2;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
ntotal += n;
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
109
|
void Index2Layer::search(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
110
|
+
idx_t /*n*/,
|
|
111
|
+
const float* /*x*/,
|
|
112
|
+
idx_t /*k*/,
|
|
113
|
+
float* /*distances*/,
|
|
114
|
+
idx_t* /*labels*/) const {
|
|
115
|
+
FAISS_THROW_MSG("not implemented");
|
|
171
116
|
}
|
|
172
117
|
|
|
118
|
+
void Index2Layer::transfer_to_IVFPQ(IndexIVFPQ& other) const {
|
|
119
|
+
FAISS_THROW_IF_NOT(other.nlist == q1.nlist);
|
|
120
|
+
FAISS_THROW_IF_NOT(other.code_size == code_size_2);
|
|
121
|
+
FAISS_THROW_IF_NOT(other.ntotal == 0);
|
|
173
122
|
|
|
174
|
-
|
|
175
|
-
{
|
|
176
|
-
std::vector<float> recons1(d);
|
|
177
|
-
FAISS_THROW_IF_NOT (i0 >= 0 && i0 + ni <= ntotal);
|
|
178
|
-
const uint8_t *rp = &codes[i0 * code_size];
|
|
179
|
-
|
|
180
|
-
for (idx_t i = 0; i < ni; i++) {
|
|
181
|
-
idx_t key = 0;
|
|
182
|
-
memcpy (&key, rp, code_size_1);
|
|
183
|
-
q1.quantizer->reconstruct (key, recons1.data());
|
|
184
|
-
rp += code_size_1;
|
|
185
|
-
pq.decode (rp, recons);
|
|
186
|
-
for (idx_t j = 0; j < d; j++) {
|
|
187
|
-
recons[j] += recons1[j];
|
|
188
|
-
}
|
|
189
|
-
rp += code_size_2;
|
|
190
|
-
recons += d;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
void Index2Layer::transfer_to_IVFPQ (IndexIVFPQ & other) const
|
|
195
|
-
{
|
|
196
|
-
FAISS_THROW_IF_NOT (other.nlist == q1.nlist);
|
|
197
|
-
FAISS_THROW_IF_NOT (other.code_size == code_size_2);
|
|
198
|
-
FAISS_THROW_IF_NOT (other.ntotal == 0);
|
|
199
|
-
|
|
200
|
-
const uint8_t *rp = codes.data();
|
|
123
|
+
const uint8_t* rp = codes.data();
|
|
201
124
|
|
|
202
125
|
for (idx_t i = 0; i < ntotal; i++) {
|
|
203
126
|
idx_t key = 0;
|
|
204
|
-
memcpy
|
|
127
|
+
memcpy(&key, rp, code_size_1);
|
|
205
128
|
rp += code_size_1;
|
|
206
|
-
other.invlists->add_entry
|
|
129
|
+
other.invlists->add_entry(key, i, rp);
|
|
207
130
|
rp += code_size_2;
|
|
208
131
|
}
|
|
209
132
|
|
|
210
133
|
other.ntotal = ntotal;
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
void Index2Layer::reconstruct(idx_t key, float* recons) const
|
|
217
|
-
{
|
|
218
|
-
reconstruct_n (key, 1, recons);
|
|
219
134
|
}
|
|
220
135
|
|
|
221
|
-
void Index2Layer::reset()
|
|
222
|
-
{
|
|
223
|
-
ntotal = 0;
|
|
224
|
-
codes.clear ();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
136
|
namespace {
|
|
229
137
|
|
|
230
|
-
|
|
231
138
|
struct Distance2Level : DistanceComputer {
|
|
232
139
|
size_t d;
|
|
233
140
|
const Index2Layer& storage;
|
|
234
141
|
std::vector<float> buf;
|
|
235
|
-
const float
|
|
142
|
+
const float* q;
|
|
236
143
|
|
|
237
144
|
const float *pq_l1_tab, *pq_l2_tab;
|
|
238
145
|
|
|
239
|
-
explicit Distance2Level(const Index2Layer& storage)
|
|
240
|
-
: storage(storage) {
|
|
146
|
+
explicit Distance2Level(const Index2Layer& storage) : storage(storage) {
|
|
241
147
|
d = storage.d;
|
|
242
148
|
FAISS_ASSERT(storage.pq.dsub == 4);
|
|
243
149
|
pq_l2_tab = storage.pq.centroids.data();
|
|
@@ -250,67 +156,64 @@ struct Distance2Level : DistanceComputer {
|
|
|
250
156
|
return fvec_L2sqr(buf.data() + d, buf.data(), d);
|
|
251
157
|
}
|
|
252
158
|
|
|
253
|
-
void set_query(const float
|
|
159
|
+
void set_query(const float* x) override {
|
|
254
160
|
q = x;
|
|
255
161
|
}
|
|
256
162
|
};
|
|
257
163
|
|
|
258
164
|
// well optimized for xNN+PQNN
|
|
259
165
|
struct DistanceXPQ4 : Distance2Level {
|
|
260
|
-
|
|
261
166
|
int M, k;
|
|
262
167
|
|
|
263
168
|
explicit DistanceXPQ4(const Index2Layer& storage)
|
|
264
|
-
|
|
265
|
-
const IndexFlat
|
|
266
|
-
|
|
169
|
+
: Distance2Level(storage) {
|
|
170
|
+
const IndexFlat* quantizer =
|
|
171
|
+
dynamic_cast<IndexFlat*>(storage.q1.quantizer);
|
|
267
172
|
|
|
268
173
|
FAISS_ASSERT(quantizer);
|
|
269
174
|
M = storage.pq.M;
|
|
270
|
-
pq_l1_tab = quantizer->
|
|
175
|
+
pq_l1_tab = quantizer->get_xb();
|
|
271
176
|
}
|
|
272
177
|
|
|
273
|
-
float operator
|
|
178
|
+
float operator()(idx_t i) override {
|
|
274
179
|
#ifdef __SSE3__
|
|
275
|
-
const uint8_t
|
|
180
|
+
const uint8_t* code = storage.codes.data() + i * storage.code_size;
|
|
276
181
|
long key = 0;
|
|
277
|
-
memcpy
|
|
182
|
+
memcpy(&key, code, storage.code_size_1);
|
|
278
183
|
code += storage.code_size_1;
|
|
279
184
|
|
|
280
185
|
// walking pointers
|
|
281
|
-
const float
|
|
282
|
-
const __m128
|
|
283
|
-
const __m128
|
|
186
|
+
const float* qa = q;
|
|
187
|
+
const __m128* l1_t = (const __m128*)(pq_l1_tab + d * key);
|
|
188
|
+
const __m128* pq_l2_t = (const __m128*)pq_l2_tab;
|
|
284
189
|
__m128 accu = _mm_setzero_ps();
|
|
285
190
|
|
|
286
191
|
for (int m = 0; m < M; m++) {
|
|
287
192
|
__m128 qi = _mm_loadu_ps(qa);
|
|
288
|
-
__m128 recons = l1_t[m]
|
|
289
|
-
__m128 diff = qi
|
|
290
|
-
accu
|
|
193
|
+
__m128 recons = _mm_add_ps(l1_t[m], pq_l2_t[*code++]);
|
|
194
|
+
__m128 diff = _mm_sub_ps(qi, recons);
|
|
195
|
+
accu = _mm_add_ps(accu, _mm_mul_ps(diff, diff));
|
|
291
196
|
pq_l2_t += 256;
|
|
292
197
|
qa += 4;
|
|
293
198
|
}
|
|
294
199
|
|
|
295
|
-
accu = _mm_hadd_ps
|
|
296
|
-
accu = _mm_hadd_ps
|
|
297
|
-
return
|
|
200
|
+
accu = _mm_hadd_ps(accu, accu);
|
|
201
|
+
accu = _mm_hadd_ps(accu, accu);
|
|
202
|
+
return _mm_cvtss_f32(accu);
|
|
298
203
|
#else
|
|
299
204
|
FAISS_THROW_MSG("not implemented for non-x64 platforms");
|
|
300
205
|
#endif
|
|
301
206
|
}
|
|
302
|
-
|
|
303
207
|
};
|
|
304
208
|
|
|
305
209
|
// well optimized for 2xNN+PQNN
|
|
306
210
|
struct Distance2xXPQ4 : Distance2Level {
|
|
307
|
-
|
|
308
211
|
int M_2, mi_nbits;
|
|
309
212
|
|
|
310
213
|
explicit Distance2xXPQ4(const Index2Layer& storage)
|
|
311
|
-
|
|
312
|
-
const MultiIndexQuantizer
|
|
313
|
-
|
|
214
|
+
: Distance2Level(storage) {
|
|
215
|
+
const MultiIndexQuantizer* mi =
|
|
216
|
+
dynamic_cast<MultiIndexQuantizer*>(storage.q1.quantizer);
|
|
314
217
|
|
|
315
218
|
FAISS_ASSERT(mi);
|
|
316
219
|
FAISS_ASSERT(storage.pq.M % 2 == 0);
|
|
@@ -319,59 +222,55 @@ struct Distance2xXPQ4 : Distance2Level {
|
|
|
319
222
|
pq_l1_tab = mi->pq.centroids.data();
|
|
320
223
|
}
|
|
321
224
|
|
|
322
|
-
float operator
|
|
323
|
-
const uint8_t
|
|
225
|
+
float operator()(idx_t i) override {
|
|
226
|
+
const uint8_t* code = storage.codes.data() + i * storage.code_size;
|
|
324
227
|
long key01 = 0;
|
|
325
|
-
memcpy
|
|
228
|
+
memcpy(&key01, code, storage.code_size_1);
|
|
326
229
|
code += storage.code_size_1;
|
|
327
230
|
#ifdef __SSE3__
|
|
328
231
|
|
|
329
232
|
// walking pointers
|
|
330
|
-
const float
|
|
331
|
-
const __m128
|
|
332
|
-
const __m128
|
|
233
|
+
const float* qa = q;
|
|
234
|
+
const __m128* pq_l1_t = (const __m128*)pq_l1_tab;
|
|
235
|
+
const __m128* pq_l2_t = (const __m128*)pq_l2_tab;
|
|
333
236
|
__m128 accu = _mm_setzero_ps();
|
|
334
237
|
|
|
335
238
|
for (int mi_m = 0; mi_m < 2; mi_m++) {
|
|
336
239
|
long l1_idx = key01 & ((1L << mi_nbits) - 1);
|
|
337
|
-
const __m128
|
|
240
|
+
const __m128* pq_l1 = pq_l1_t + M_2 * l1_idx;
|
|
338
241
|
|
|
339
242
|
for (int m = 0; m < M_2; m++) {
|
|
340
243
|
__m128 qi = _mm_loadu_ps(qa);
|
|
341
|
-
__m128 recons = pq_l1[m]
|
|
342
|
-
__m128 diff = qi
|
|
343
|
-
accu
|
|
244
|
+
__m128 recons = _mm_add_ps(pq_l1[m], pq_l2_t[*code++]);
|
|
245
|
+
__m128 diff = _mm_sub_ps(qi, recons);
|
|
246
|
+
accu = _mm_add_ps(accu, _mm_mul_ps(diff, diff));
|
|
344
247
|
pq_l2_t += 256;
|
|
345
248
|
qa += 4;
|
|
346
249
|
}
|
|
347
250
|
pq_l1_t += M_2 << mi_nbits;
|
|
348
251
|
key01 >>= mi_nbits;
|
|
349
252
|
}
|
|
350
|
-
accu = _mm_hadd_ps
|
|
351
|
-
accu = _mm_hadd_ps
|
|
352
|
-
return
|
|
253
|
+
accu = _mm_hadd_ps(accu, accu);
|
|
254
|
+
accu = _mm_hadd_ps(accu, accu);
|
|
255
|
+
return _mm_cvtss_f32(accu);
|
|
353
256
|
#else
|
|
354
257
|
FAISS_THROW_MSG("not implemented for non-x64 platforms");
|
|
355
258
|
#endif
|
|
356
259
|
}
|
|
357
|
-
|
|
358
260
|
};
|
|
359
261
|
|
|
262
|
+
} // namespace
|
|
360
263
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
DistanceComputer * Index2Layer::get_distance_computer() const {
|
|
264
|
+
DistanceComputer* Index2Layer::get_distance_computer() const {
|
|
365
265
|
#ifdef __SSE3__
|
|
366
|
-
const MultiIndexQuantizer
|
|
367
|
-
|
|
266
|
+
const MultiIndexQuantizer* mi =
|
|
267
|
+
dynamic_cast<MultiIndexQuantizer*>(q1.quantizer);
|
|
368
268
|
|
|
369
269
|
if (mi && pq.M % 2 == 0 && pq.dsub == 4) {
|
|
370
270
|
return new Distance2xXPQ4(*this);
|
|
371
271
|
}
|
|
372
272
|
|
|
373
|
-
const IndexFlat
|
|
374
|
-
dynamic_cast<IndexFlat*> (q1.quantizer);
|
|
273
|
+
const IndexFlat* fl = dynamic_cast<IndexFlat*>(q1.quantizer);
|
|
375
274
|
|
|
376
275
|
if (fl && pq.dsub == 4) {
|
|
377
276
|
return new DistanceXPQ4(*this);
|
|
@@ -381,57 +280,60 @@ DistanceComputer * Index2Layer::get_distance_computer() const {
|
|
|
381
280
|
return Index::get_distance_computer();
|
|
382
281
|
}
|
|
383
282
|
|
|
384
|
-
|
|
385
283
|
/* The standalone codec interface */
|
|
386
|
-
size_t Index2Layer::sa_code_size () const
|
|
387
|
-
{
|
|
388
|
-
return code_size;
|
|
389
|
-
}
|
|
390
284
|
|
|
391
|
-
void Index2Layer::sa_encode
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
285
|
+
void Index2Layer::sa_encode(idx_t n, const float* x, uint8_t* bytes) const {
|
|
286
|
+
FAISS_THROW_IF_NOT(is_trained);
|
|
287
|
+
|
|
288
|
+
idx_t bs = 32768;
|
|
289
|
+
if (n > bs) {
|
|
290
|
+
for (idx_t i0 = 0; i0 < n; i0 += bs) {
|
|
291
|
+
idx_t i1 = std::min(i0 + bs, n);
|
|
292
|
+
if (verbose) {
|
|
293
|
+
printf("Index2Layer::add: adding %" PRId64 ":%" PRId64
|
|
294
|
+
" / %" PRId64 "\n",
|
|
295
|
+
i0,
|
|
296
|
+
i1,
|
|
297
|
+
n);
|
|
298
|
+
}
|
|
299
|
+
sa_encode(i1 - i0, x + i0 * d, bytes + i0 * code_size);
|
|
300
|
+
}
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
std::unique_ptr<int64_t[]> list_nos(new int64_t[n]);
|
|
305
|
+
q1.quantizer->assign(n, x, list_nos.get());
|
|
396
306
|
std::vector<float> residuals(n * d);
|
|
397
307
|
for (idx_t i = 0; i < n; i++) {
|
|
398
|
-
q1.quantizer->compute_residual
|
|
399
|
-
|
|
308
|
+
q1.quantizer->compute_residual(
|
|
309
|
+
x + i * d, residuals.data() + i * d, list_nos[i]);
|
|
400
310
|
}
|
|
401
|
-
pq.compute_codes
|
|
311
|
+
pq.compute_codes(residuals.data(), bytes, n);
|
|
402
312
|
|
|
403
313
|
for (idx_t i = n - 1; i >= 0; i--) {
|
|
404
|
-
uint8_t
|
|
405
|
-
memmove
|
|
406
|
-
|
|
407
|
-
q1.encode_listno (list_nos[i], code);
|
|
314
|
+
uint8_t* code = bytes + i * code_size;
|
|
315
|
+
memmove(code + code_size_1, bytes + i * code_size_2, code_size_2);
|
|
316
|
+
q1.encode_listno(list_nos[i], code);
|
|
408
317
|
}
|
|
409
|
-
|
|
410
318
|
}
|
|
411
319
|
|
|
412
|
-
void Index2Layer::sa_decode
|
|
413
|
-
{
|
|
414
|
-
|
|
320
|
+
void Index2Layer::sa_decode(idx_t n, const uint8_t* bytes, float* x) const {
|
|
415
321
|
#pragma omp parallel
|
|
416
322
|
{
|
|
417
|
-
std::vector<float> residual
|
|
323
|
+
std::vector<float> residual(d);
|
|
418
324
|
|
|
419
325
|
#pragma omp for
|
|
420
326
|
for (idx_t i = 0; i < n; i++) {
|
|
421
|
-
const uint8_t
|
|
422
|
-
int64_t list_no = q1.decode_listno
|
|
423
|
-
float
|
|
424
|
-
pq.decode
|
|
425
|
-
q1.quantizer->reconstruct
|
|
327
|
+
const uint8_t* code = bytes + i * code_size;
|
|
328
|
+
int64_t list_no = q1.decode_listno(code);
|
|
329
|
+
float* xi = x + i * d;
|
|
330
|
+
pq.decode(code + code_size_1, xi);
|
|
331
|
+
q1.quantizer->reconstruct(list_no, residual.data());
|
|
426
332
|
for (int j = 0; j < d; j++) {
|
|
427
333
|
xi[j] += residual[j];
|
|
428
334
|
}
|
|
429
335
|
}
|
|
430
336
|
}
|
|
431
|
-
|
|
432
337
|
}
|
|
433
338
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
339
|
} // namespace faiss
|
|
@@ -11,75 +11,61 @@
|
|
|
11
11
|
|
|
12
12
|
#include <vector>
|
|
13
13
|
|
|
14
|
-
#include <faiss/
|
|
14
|
+
#include <faiss/IndexFlatCodes.h>
|
|
15
15
|
#include <faiss/IndexIVF.h>
|
|
16
|
+
#include <faiss/IndexPQ.h>
|
|
16
17
|
|
|
17
18
|
namespace faiss {
|
|
18
19
|
|
|
19
20
|
struct IndexIVFPQ;
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
/** Same as an IndexIVFPQ without the inverted lists: codes are stored
|
|
23
|
+
* sequentially
|
|
23
24
|
*
|
|
24
25
|
* The class is mainly inteded to store encoded vectors that can be
|
|
25
26
|
* accessed randomly, the search function is not implemented.
|
|
26
27
|
*/
|
|
27
|
-
struct Index2Layer:
|
|
28
|
+
struct Index2Layer : IndexFlatCodes {
|
|
28
29
|
/// first level quantizer
|
|
29
30
|
Level1Quantizer q1;
|
|
30
31
|
|
|
31
32
|
/// second level quantizer is always a PQ
|
|
32
33
|
ProductQuantizer pq;
|
|
33
34
|
|
|
34
|
-
/// Codes. Size ntotal * code_size.
|
|
35
|
-
std::vector<uint8_t> codes;
|
|
36
|
-
|
|
37
35
|
/// size of the code for the first level (ceil(log8(q1.nlist)))
|
|
38
36
|
size_t code_size_1;
|
|
39
37
|
|
|
40
38
|
/// size of the code for the second level
|
|
41
39
|
size_t code_size_2;
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
Index2Layer(
|
|
42
|
+
Index* quantizer,
|
|
43
|
+
size_t nlist,
|
|
44
|
+
int M,
|
|
45
|
+
int nbit = 8,
|
|
46
|
+
MetricType metric = METRIC_L2);
|
|
49
47
|
|
|
50
|
-
Index2Layer
|
|
51
|
-
~Index2Layer
|
|
48
|
+
Index2Layer();
|
|
49
|
+
~Index2Layer();
|
|
52
50
|
|
|
53
51
|
void train(idx_t n, const float* x) override;
|
|
54
52
|
|
|
55
|
-
void add(idx_t n, const float* x) override;
|
|
56
|
-
|
|
57
53
|
/// not implemented
|
|
58
54
|
void search(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
idx_t n,
|
|
56
|
+
const float* x,
|
|
57
|
+
idx_t k,
|
|
58
|
+
float* distances,
|
|
59
|
+
idx_t* labels) const override;
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
void reconstruct(idx_t key, float* recons) const override;
|
|
68
|
-
|
|
69
|
-
void reset() override;
|
|
70
|
-
|
|
71
|
-
DistanceComputer * get_distance_computer() const override;
|
|
61
|
+
DistanceComputer* get_distance_computer() const override;
|
|
72
62
|
|
|
73
63
|
/// transfer the flat codes to an IVFPQ index
|
|
74
|
-
void transfer_to_IVFPQ(IndexIVFPQ
|
|
75
|
-
|
|
64
|
+
void transfer_to_IVFPQ(IndexIVFPQ& other) const;
|
|
76
65
|
|
|
77
66
|
/* The standalone codec interface */
|
|
78
|
-
|
|
79
|
-
void
|
|
80
|
-
void sa_decode (idx_t n, const uint8_t *bytes, float *x) const override;
|
|
81
|
-
|
|
67
|
+
void sa_encode(idx_t n, const float* x, uint8_t* bytes) const override;
|
|
68
|
+
void sa_decode(idx_t n, const uint8_t* bytes, float* x) const override;
|
|
82
69
|
};
|
|
83
70
|
|
|
84
|
-
|
|
85
71
|
} // namespace faiss
|