faiss 0.2.3 → 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 +9 -0
- data/LICENSE.txt +1 -1
- 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/Clustering.cpp +32 -0
- data/vendor/faiss/faiss/Clustering.h +14 -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 +24 -93
- data/vendor/faiss/faiss/Index2Layer.h +8 -17
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +610 -0
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +253 -0
- 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 +52 -69
- data/vendor/faiss/faiss/IndexFlat.h +16 -19
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +101 -0
- data/vendor/faiss/faiss/IndexFlatCodes.h +59 -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 +200 -40
- data/vendor/faiss/faiss/IndexIVF.h +59 -22
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +393 -0
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +183 -0
- 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 +43 -26
- data/vendor/faiss/faiss/IndexIVFFlat.h +4 -2
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +238 -53
- data/vendor/faiss/faiss/IndexIVFPQ.h +6 -2
- 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 +63 -40
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +23 -7
- data/vendor/faiss/faiss/IndexLSH.cpp +8 -32
- data/vendor/faiss/faiss/IndexLSH.h +4 -16
- data/vendor/faiss/faiss/IndexLattice.cpp +7 -1
- data/vendor/faiss/faiss/IndexLattice.h +3 -1
- data/vendor/faiss/faiss/IndexNNDescent.cpp +4 -5
- data/vendor/faiss/faiss/IndexNNDescent.h +2 -1
- data/vendor/faiss/faiss/IndexNSG.cpp +37 -5
- data/vendor/faiss/faiss/IndexNSG.h +25 -1
- data/vendor/faiss/faiss/IndexPQ.cpp +108 -120
- data/vendor/faiss/faiss/IndexPQ.h +21 -22
- 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 +36 -4
- data/vendor/faiss/faiss/IndexRefine.h +14 -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 +28 -43
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +8 -23
- 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 +45 -1
- data/vendor/faiss/faiss/VectorTransform.h +25 -4
- data/vendor/faiss/faiss/clone_index.cpp +26 -3
- 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 +2 -6
- data/vendor/faiss/faiss/gpu/GpuIcmEncoder.h +60 -0
- 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 +331 -29
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +110 -19
- 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 +133 -32
- 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 +378 -217
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +106 -29
- 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 -4
- data/vendor/faiss/faiss/impl/NSG.h +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 +521 -55
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +94 -16
- data/vendor/faiss/faiss/impl/ResultHandler.h +96 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +108 -191
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +18 -18
- data/vendor/faiss/faiss/impl/index_read.cpp +338 -24
- data/vendor/faiss/faiss/impl/index_write.cpp +300 -18
- data/vendor/faiss/faiss/impl/io.cpp +1 -1
- data/vendor/faiss/faiss/impl/io_macros.h +20 -0
- data/vendor/faiss/faiss/impl/kmeans1d.cpp +303 -0
- data/vendor/faiss/faiss/impl/kmeans1d.h +48 -0
- 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 +772 -412
- data/vendor/faiss/faiss/index_factory.h +3 -0
- 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 +384 -58
- data/vendor/faiss/faiss/utils/distances.h +149 -18
- data/vendor/faiss/faiss/utils/distances_simd.cpp +776 -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
- data/vendor/faiss/faiss/utils/utils.h +1 -1
- metadata +46 -5
- data/vendor/faiss/faiss/IndexResidual.cpp +0 -291
- data/vendor/faiss/faiss/IndexResidual.h +0 -152
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#ifndef FAISS_INDEX_ADDITIVE_QUANTIZER_H
|
|
9
|
+
#define FAISS_INDEX_ADDITIVE_QUANTIZER_H
|
|
10
|
+
|
|
11
|
+
#include <faiss/impl/AdditiveQuantizer.h>
|
|
12
|
+
|
|
13
|
+
#include <cstdint>
|
|
14
|
+
#include <vector>
|
|
15
|
+
|
|
16
|
+
#include <faiss/IndexFlatCodes.h>
|
|
17
|
+
#include <faiss/impl/LocalSearchQuantizer.h>
|
|
18
|
+
#include <faiss/impl/ProductAdditiveQuantizer.h>
|
|
19
|
+
#include <faiss/impl/ResidualQuantizer.h>
|
|
20
|
+
#include <faiss/impl/platform_macros.h>
|
|
21
|
+
|
|
22
|
+
namespace faiss {
|
|
23
|
+
|
|
24
|
+
/// Abstract class for additive quantizers. The search functions are in common.
|
|
25
|
+
struct IndexAdditiveQuantizer : IndexFlatCodes {
|
|
26
|
+
// the quantizer, this points to the relevant field in the inheriting
|
|
27
|
+
// classes
|
|
28
|
+
AdditiveQuantizer* aq;
|
|
29
|
+
using Search_type_t = AdditiveQuantizer::Search_type_t;
|
|
30
|
+
|
|
31
|
+
explicit IndexAdditiveQuantizer(
|
|
32
|
+
idx_t d,
|
|
33
|
+
AdditiveQuantizer* aq,
|
|
34
|
+
MetricType metric = METRIC_L2);
|
|
35
|
+
|
|
36
|
+
void search(
|
|
37
|
+
idx_t n,
|
|
38
|
+
const float* x,
|
|
39
|
+
idx_t k,
|
|
40
|
+
float* distances,
|
|
41
|
+
idx_t* labels,
|
|
42
|
+
const SearchParameters* params = nullptr) const override;
|
|
43
|
+
|
|
44
|
+
/* The standalone codec interface */
|
|
45
|
+
void sa_encode(idx_t n, const float* x, uint8_t* bytes) const override;
|
|
46
|
+
|
|
47
|
+
void sa_decode(idx_t n, const uint8_t* bytes, float* x) const override;
|
|
48
|
+
|
|
49
|
+
FlatCodesDistanceComputer* get_FlatCodesDistanceComputer() const override;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** Index based on a residual quantizer. Stored vectors are
|
|
53
|
+
* approximated by residual quantization codes.
|
|
54
|
+
* Can also be used as a codec
|
|
55
|
+
*/
|
|
56
|
+
struct IndexResidualQuantizer : IndexAdditiveQuantizer {
|
|
57
|
+
/// The residual quantizer used to encode the vectors
|
|
58
|
+
ResidualQuantizer rq;
|
|
59
|
+
|
|
60
|
+
/** Constructor.
|
|
61
|
+
*
|
|
62
|
+
* @param d dimensionality of the input vectors
|
|
63
|
+
* @param M number of subquantizers
|
|
64
|
+
* @param nbits number of bit per subvector index
|
|
65
|
+
*/
|
|
66
|
+
IndexResidualQuantizer(
|
|
67
|
+
int d, ///< dimensionality of the input vectors
|
|
68
|
+
size_t M, ///< number of subquantizers
|
|
69
|
+
size_t nbits, ///< number of bit per subvector index
|
|
70
|
+
MetricType metric = METRIC_L2,
|
|
71
|
+
Search_type_t search_type = AdditiveQuantizer::ST_decompress);
|
|
72
|
+
|
|
73
|
+
IndexResidualQuantizer(
|
|
74
|
+
int d,
|
|
75
|
+
const std::vector<size_t>& nbits,
|
|
76
|
+
MetricType metric = METRIC_L2,
|
|
77
|
+
Search_type_t search_type = AdditiveQuantizer::ST_decompress);
|
|
78
|
+
|
|
79
|
+
IndexResidualQuantizer();
|
|
80
|
+
|
|
81
|
+
void train(idx_t n, const float* x) override;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
struct IndexLocalSearchQuantizer : IndexAdditiveQuantizer {
|
|
85
|
+
LocalSearchQuantizer lsq;
|
|
86
|
+
|
|
87
|
+
/** Constructor.
|
|
88
|
+
*
|
|
89
|
+
* @param d dimensionality of the input vectors
|
|
90
|
+
* @param M number of subquantizers
|
|
91
|
+
* @param nbits number of bit per subvector index
|
|
92
|
+
*/
|
|
93
|
+
IndexLocalSearchQuantizer(
|
|
94
|
+
int d, ///< dimensionality of the input vectors
|
|
95
|
+
size_t M, ///< number of subquantizers
|
|
96
|
+
size_t nbits, ///< number of bit per subvector index
|
|
97
|
+
MetricType metric = METRIC_L2,
|
|
98
|
+
Search_type_t search_type = AdditiveQuantizer::ST_decompress);
|
|
99
|
+
|
|
100
|
+
IndexLocalSearchQuantizer();
|
|
101
|
+
|
|
102
|
+
void train(idx_t n, const float* x) override;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** Index based on a product residual quantizer.
|
|
106
|
+
*/
|
|
107
|
+
struct IndexProductResidualQuantizer : IndexAdditiveQuantizer {
|
|
108
|
+
/// The product residual quantizer used to encode the vectors
|
|
109
|
+
ProductResidualQuantizer prq;
|
|
110
|
+
|
|
111
|
+
/** Constructor.
|
|
112
|
+
*
|
|
113
|
+
* @param d dimensionality of the input vectors
|
|
114
|
+
* @param nsplits number of residual quantizers
|
|
115
|
+
* @param Msub number of subquantizers per RQ
|
|
116
|
+
* @param nbits number of bit per subvector index
|
|
117
|
+
*/
|
|
118
|
+
IndexProductResidualQuantizer(
|
|
119
|
+
int d, ///< dimensionality of the input vectors
|
|
120
|
+
size_t nsplits, ///< number of residual quantizers
|
|
121
|
+
size_t Msub, ///< number of subquantizers per RQ
|
|
122
|
+
size_t nbits, ///< number of bit per subvector index
|
|
123
|
+
MetricType metric = METRIC_L2,
|
|
124
|
+
Search_type_t search_type = AdditiveQuantizer::ST_decompress);
|
|
125
|
+
|
|
126
|
+
IndexProductResidualQuantizer();
|
|
127
|
+
|
|
128
|
+
void train(idx_t n, const float* x) override;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/** Index based on a product local search quantizer.
|
|
132
|
+
*/
|
|
133
|
+
struct IndexProductLocalSearchQuantizer : IndexAdditiveQuantizer {
|
|
134
|
+
/// The product local search quantizer used to encode the vectors
|
|
135
|
+
ProductLocalSearchQuantizer plsq;
|
|
136
|
+
|
|
137
|
+
/** Constructor.
|
|
138
|
+
*
|
|
139
|
+
* @param d dimensionality of the input vectors
|
|
140
|
+
* @param nsplits number of local search quantizers
|
|
141
|
+
* @param Msub number of subquantizers per LSQ
|
|
142
|
+
* @param nbits number of bit per subvector index
|
|
143
|
+
*/
|
|
144
|
+
IndexProductLocalSearchQuantizer(
|
|
145
|
+
int d, ///< dimensionality of the input vectors
|
|
146
|
+
size_t nsplits, ///< number of local search quantizers
|
|
147
|
+
size_t Msub, ///< number of subquantizers per LSQ
|
|
148
|
+
size_t nbits, ///< number of bit per subvector index
|
|
149
|
+
MetricType metric = METRIC_L2,
|
|
150
|
+
Search_type_t search_type = AdditiveQuantizer::ST_decompress);
|
|
151
|
+
|
|
152
|
+
IndexProductLocalSearchQuantizer();
|
|
153
|
+
|
|
154
|
+
void train(idx_t n, const float* x) override;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/** A "virtual" index where the elements are the residual quantizer centroids.
|
|
158
|
+
*
|
|
159
|
+
* Intended for use as a coarse quantizer in an IndexIVF.
|
|
160
|
+
*/
|
|
161
|
+
struct AdditiveCoarseQuantizer : Index {
|
|
162
|
+
AdditiveQuantizer* aq;
|
|
163
|
+
|
|
164
|
+
explicit AdditiveCoarseQuantizer(
|
|
165
|
+
idx_t d = 0,
|
|
166
|
+
AdditiveQuantizer* aq = nullptr,
|
|
167
|
+
MetricType metric = METRIC_L2);
|
|
168
|
+
|
|
169
|
+
/// norms of centroids, useful for knn-search
|
|
170
|
+
std::vector<float> centroid_norms;
|
|
171
|
+
|
|
172
|
+
/// N/A
|
|
173
|
+
void add(idx_t n, const float* x) override;
|
|
174
|
+
|
|
175
|
+
void search(
|
|
176
|
+
idx_t n,
|
|
177
|
+
const float* x,
|
|
178
|
+
idx_t k,
|
|
179
|
+
float* distances,
|
|
180
|
+
idx_t* labels,
|
|
181
|
+
const SearchParameters* params = nullptr) const override;
|
|
182
|
+
|
|
183
|
+
void reconstruct(idx_t key, float* recons) const override;
|
|
184
|
+
void train(idx_t n, const float* x) override;
|
|
185
|
+
|
|
186
|
+
/// N/A
|
|
187
|
+
void reset() override;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/** The ResidualCoarseQuantizer is a bit specialized compared to the
|
|
191
|
+
* default AdditiveCoarseQuantizer because it can use a beam search
|
|
192
|
+
* at search time (slow but may be useful for very large vocabularies) */
|
|
193
|
+
struct ResidualCoarseQuantizer : AdditiveCoarseQuantizer {
|
|
194
|
+
/// The residual quantizer used to encode the vectors
|
|
195
|
+
ResidualQuantizer rq;
|
|
196
|
+
|
|
197
|
+
/// factor between the beam size and the search k
|
|
198
|
+
/// if negative, use exact search-to-centroid
|
|
199
|
+
float beam_factor;
|
|
200
|
+
|
|
201
|
+
/// computes centroid norms if required
|
|
202
|
+
void set_beam_factor(float new_beam_factor);
|
|
203
|
+
|
|
204
|
+
/** Constructor.
|
|
205
|
+
*
|
|
206
|
+
* @param d dimensionality of the input vectors
|
|
207
|
+
* @param M number of subquantizers
|
|
208
|
+
* @param nbits number of bit per subvector index
|
|
209
|
+
*/
|
|
210
|
+
ResidualCoarseQuantizer(
|
|
211
|
+
int d, ///< dimensionality of the input vectors
|
|
212
|
+
size_t M, ///< number of subquantizers
|
|
213
|
+
size_t nbits, ///< number of bit per subvector index
|
|
214
|
+
MetricType metric = METRIC_L2);
|
|
215
|
+
|
|
216
|
+
ResidualCoarseQuantizer(
|
|
217
|
+
int d,
|
|
218
|
+
const std::vector<size_t>& nbits,
|
|
219
|
+
MetricType metric = METRIC_L2);
|
|
220
|
+
|
|
221
|
+
void search(
|
|
222
|
+
idx_t n,
|
|
223
|
+
const float* x,
|
|
224
|
+
idx_t k,
|
|
225
|
+
float* distances,
|
|
226
|
+
idx_t* labels,
|
|
227
|
+
const SearchParameters* params = nullptr) const override;
|
|
228
|
+
|
|
229
|
+
ResidualCoarseQuantizer();
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
struct LocalSearchCoarseQuantizer : AdditiveCoarseQuantizer {
|
|
233
|
+
/// The residual quantizer used to encode the vectors
|
|
234
|
+
LocalSearchQuantizer lsq;
|
|
235
|
+
|
|
236
|
+
/** Constructor.
|
|
237
|
+
*
|
|
238
|
+
* @param d dimensionality of the input vectors
|
|
239
|
+
* @param M number of subquantizers
|
|
240
|
+
* @param nbits number of bit per subvector index
|
|
241
|
+
*/
|
|
242
|
+
LocalSearchCoarseQuantizer(
|
|
243
|
+
int d, ///< dimensionality of the input vectors
|
|
244
|
+
size_t M, ///< number of subquantizers
|
|
245
|
+
size_t nbits, ///< number of bit per subvector index
|
|
246
|
+
MetricType metric = METRIC_L2);
|
|
247
|
+
|
|
248
|
+
LocalSearchCoarseQuantizer();
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
} // namespace faiss
|
|
252
|
+
|
|
253
|
+
#endif
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include <faiss/IndexAdditiveQuantizerFastScan.h>
|
|
9
|
+
|
|
10
|
+
#include <limits.h>
|
|
11
|
+
#include <cassert>
|
|
12
|
+
#include <memory>
|
|
13
|
+
|
|
14
|
+
#include <omp.h>
|
|
15
|
+
|
|
16
|
+
#include <faiss/impl/FaissAssert.h>
|
|
17
|
+
#include <faiss/impl/LocalSearchQuantizer.h>
|
|
18
|
+
#include <faiss/impl/LookupTableScaler.h>
|
|
19
|
+
#include <faiss/impl/ResidualQuantizer.h>
|
|
20
|
+
#include <faiss/impl/pq4_fast_scan.h>
|
|
21
|
+
#include <faiss/utils/quantize_lut.h>
|
|
22
|
+
#include <faiss/utils/utils.h>
|
|
23
|
+
|
|
24
|
+
namespace faiss {
|
|
25
|
+
|
|
26
|
+
inline size_t roundup(size_t a, size_t b) {
|
|
27
|
+
return (a + b - 1) / b * b;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
IndexAdditiveQuantizerFastScan::IndexAdditiveQuantizerFastScan(
|
|
31
|
+
AdditiveQuantizer* aq,
|
|
32
|
+
MetricType metric,
|
|
33
|
+
int bbs) {
|
|
34
|
+
init(aq, metric, bbs);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
void IndexAdditiveQuantizerFastScan::init(
|
|
38
|
+
AdditiveQuantizer* aq,
|
|
39
|
+
MetricType metric,
|
|
40
|
+
int bbs) {
|
|
41
|
+
FAISS_THROW_IF_NOT(aq != nullptr);
|
|
42
|
+
FAISS_THROW_IF_NOT(!aq->nbits.empty());
|
|
43
|
+
FAISS_THROW_IF_NOT(aq->nbits[0] == 4);
|
|
44
|
+
if (metric == METRIC_INNER_PRODUCT) {
|
|
45
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
46
|
+
aq->search_type == AdditiveQuantizer::ST_LUT_nonorm,
|
|
47
|
+
"Search type must be ST_LUT_nonorm for IP metric");
|
|
48
|
+
} else {
|
|
49
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
50
|
+
aq->search_type == AdditiveQuantizer::ST_norm_lsq2x4 ||
|
|
51
|
+
aq->search_type == AdditiveQuantizer::ST_norm_rq2x4,
|
|
52
|
+
"Search type must be lsq2x4 or rq2x4 for L2 metric");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this->aq = aq;
|
|
56
|
+
if (metric == METRIC_L2) {
|
|
57
|
+
M = aq->M + 2; // 2x4 bits AQ
|
|
58
|
+
} else {
|
|
59
|
+
M = aq->M;
|
|
60
|
+
}
|
|
61
|
+
init_fastscan(aq->d, M, 4, metric, bbs);
|
|
62
|
+
|
|
63
|
+
max_train_points = 1024 * ksub * M;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
IndexAdditiveQuantizerFastScan::IndexAdditiveQuantizerFastScan()
|
|
67
|
+
: IndexFastScan() {
|
|
68
|
+
is_trained = false;
|
|
69
|
+
aq = nullptr;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
IndexAdditiveQuantizerFastScan::IndexAdditiveQuantizerFastScan(
|
|
73
|
+
const IndexAdditiveQuantizer& orig,
|
|
74
|
+
int bbs) {
|
|
75
|
+
init(orig.aq, orig.metric_type, bbs);
|
|
76
|
+
|
|
77
|
+
ntotal = orig.ntotal;
|
|
78
|
+
is_trained = orig.is_trained;
|
|
79
|
+
orig_codes = orig.codes.data();
|
|
80
|
+
|
|
81
|
+
ntotal2 = roundup(ntotal, bbs);
|
|
82
|
+
codes.resize(ntotal2 * M2 / 2);
|
|
83
|
+
pq4_pack_codes(orig_codes, ntotal, M, ntotal2, bbs, M2, codes.get());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
IndexAdditiveQuantizerFastScan::~IndexAdditiveQuantizerFastScan() {}
|
|
87
|
+
|
|
88
|
+
void IndexAdditiveQuantizerFastScan::train(idx_t n, const float* x_in) {
|
|
89
|
+
if (is_trained) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const int seed = 0x12345;
|
|
94
|
+
size_t nt = n;
|
|
95
|
+
const float* x = fvecs_maybe_subsample(
|
|
96
|
+
d, &nt, max_train_points, x_in, verbose, seed);
|
|
97
|
+
n = nt;
|
|
98
|
+
if (verbose) {
|
|
99
|
+
printf("training additive quantizer on %zd vectors\n", nt);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
aq->verbose = verbose;
|
|
103
|
+
aq->train(n, x);
|
|
104
|
+
if (metric_type == METRIC_L2) {
|
|
105
|
+
estimate_norm_scale(n, x);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
is_trained = true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
void IndexAdditiveQuantizerFastScan::estimate_norm_scale(
|
|
112
|
+
idx_t n,
|
|
113
|
+
const float* x_in) {
|
|
114
|
+
FAISS_THROW_IF_NOT(metric_type == METRIC_L2);
|
|
115
|
+
|
|
116
|
+
constexpr int seed = 0x980903;
|
|
117
|
+
constexpr size_t max_points_estimated = 65536;
|
|
118
|
+
size_t ns = n;
|
|
119
|
+
const float* x = fvecs_maybe_subsample(
|
|
120
|
+
d, &ns, max_points_estimated, x_in, verbose, seed);
|
|
121
|
+
n = ns;
|
|
122
|
+
std::unique_ptr<float[]> del_x;
|
|
123
|
+
if (x != x_in) {
|
|
124
|
+
del_x.reset((float*)x);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
std::vector<float> dis_tables(n * M * ksub);
|
|
128
|
+
compute_float_LUT(dis_tables.data(), n, x);
|
|
129
|
+
|
|
130
|
+
// here we compute the mean of scales for each query
|
|
131
|
+
// TODO: try max of scales
|
|
132
|
+
double scale = 0;
|
|
133
|
+
|
|
134
|
+
#pragma omp parallel for reduction(+ : scale)
|
|
135
|
+
for (idx_t i = 0; i < n; i++) {
|
|
136
|
+
const float* lut = dis_tables.data() + i * M * ksub;
|
|
137
|
+
scale += quantize_lut::aq_estimate_norm_scale(M, ksub, 2, lut);
|
|
138
|
+
}
|
|
139
|
+
scale /= n;
|
|
140
|
+
norm_scale = (int)std::roundf(std::max(scale, 1.0));
|
|
141
|
+
|
|
142
|
+
if (verbose) {
|
|
143
|
+
printf("estimated norm scale: %lf\n", scale);
|
|
144
|
+
printf("rounded norm scale: %d\n", norm_scale);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
void IndexAdditiveQuantizerFastScan::compute_codes(
|
|
149
|
+
uint8_t* tmp_codes,
|
|
150
|
+
idx_t n,
|
|
151
|
+
const float* x) const {
|
|
152
|
+
aq->compute_codes(x, tmp_codes, n);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
void IndexAdditiveQuantizerFastScan::compute_float_LUT(
|
|
156
|
+
float* lut,
|
|
157
|
+
idx_t n,
|
|
158
|
+
const float* x) const {
|
|
159
|
+
if (metric_type == METRIC_INNER_PRODUCT) {
|
|
160
|
+
aq->compute_LUT(n, x, lut, 1.0f);
|
|
161
|
+
} else {
|
|
162
|
+
// compute inner product look-up tables
|
|
163
|
+
const size_t ip_dim12 = aq->M * ksub;
|
|
164
|
+
const size_t norm_dim12 = 2 * ksub;
|
|
165
|
+
std::vector<float> ip_lut(n * ip_dim12);
|
|
166
|
+
aq->compute_LUT(n, x, ip_lut.data(), -2.0f);
|
|
167
|
+
|
|
168
|
+
// copy and rescale norm look-up tables
|
|
169
|
+
auto norm_tabs = aq->norm_tabs;
|
|
170
|
+
if (rescale_norm && norm_scale > 1 && metric_type == METRIC_L2) {
|
|
171
|
+
for (size_t i = 0; i < norm_tabs.size(); i++) {
|
|
172
|
+
norm_tabs[i] /= norm_scale;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const float* norm_lut = norm_tabs.data();
|
|
176
|
+
FAISS_THROW_IF_NOT(norm_tabs.size() == norm_dim12);
|
|
177
|
+
|
|
178
|
+
// combine them
|
|
179
|
+
for (idx_t i = 0; i < n; i++) {
|
|
180
|
+
memcpy(lut, ip_lut.data() + i * ip_dim12, ip_dim12 * sizeof(*lut));
|
|
181
|
+
lut += ip_dim12;
|
|
182
|
+
memcpy(lut, norm_lut, norm_dim12 * sizeof(*lut));
|
|
183
|
+
lut += norm_dim12;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
void IndexAdditiveQuantizerFastScan::search(
|
|
189
|
+
idx_t n,
|
|
190
|
+
const float* x,
|
|
191
|
+
idx_t k,
|
|
192
|
+
float* distances,
|
|
193
|
+
idx_t* labels,
|
|
194
|
+
const SearchParameters* params) const {
|
|
195
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
196
|
+
!params, "search params not supported for this index");
|
|
197
|
+
FAISS_THROW_IF_NOT(k > 0);
|
|
198
|
+
bool rescale = (rescale_norm && norm_scale > 1 && metric_type == METRIC_L2);
|
|
199
|
+
if (!rescale) {
|
|
200
|
+
IndexFastScan::search(n, x, k, distances, labels);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
NormTableScaler scaler(norm_scale);
|
|
205
|
+
if (metric_type == METRIC_L2) {
|
|
206
|
+
search_dispatch_implem<true>(n, x, k, distances, labels, scaler);
|
|
207
|
+
} else {
|
|
208
|
+
search_dispatch_implem<false>(n, x, k, distances, labels, scaler);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
void IndexAdditiveQuantizerFastScan::sa_decode(
|
|
213
|
+
idx_t n,
|
|
214
|
+
const uint8_t* bytes,
|
|
215
|
+
float* x) const {
|
|
216
|
+
aq->decode(bytes, x, n);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**************************************************************************************
|
|
220
|
+
* IndexResidualQuantizerFastScan
|
|
221
|
+
**************************************************************************************/
|
|
222
|
+
|
|
223
|
+
IndexResidualQuantizerFastScan::IndexResidualQuantizerFastScan(
|
|
224
|
+
int d, ///< dimensionality of the input vectors
|
|
225
|
+
size_t M, ///< number of subquantizers
|
|
226
|
+
size_t nbits, ///< number of bit per subvector index
|
|
227
|
+
MetricType metric,
|
|
228
|
+
Search_type_t search_type,
|
|
229
|
+
int bbs)
|
|
230
|
+
: rq(d, M, nbits, search_type) {
|
|
231
|
+
init(&rq, metric, bbs);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
IndexResidualQuantizerFastScan::IndexResidualQuantizerFastScan() {
|
|
235
|
+
aq = &rq;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**************************************************************************************
|
|
239
|
+
* IndexLocalSearchQuantizerFastScan
|
|
240
|
+
**************************************************************************************/
|
|
241
|
+
|
|
242
|
+
IndexLocalSearchQuantizerFastScan::IndexLocalSearchQuantizerFastScan(
|
|
243
|
+
int d,
|
|
244
|
+
size_t M, ///< number of subquantizers
|
|
245
|
+
size_t nbits, ///< number of bit per subvector index
|
|
246
|
+
MetricType metric,
|
|
247
|
+
Search_type_t search_type,
|
|
248
|
+
int bbs)
|
|
249
|
+
: lsq(d, M, nbits, search_type) {
|
|
250
|
+
init(&lsq, metric, bbs);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
IndexLocalSearchQuantizerFastScan::IndexLocalSearchQuantizerFastScan() {
|
|
254
|
+
aq = &lsq;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**************************************************************************************
|
|
258
|
+
* IndexProductResidualQuantizerFastScan
|
|
259
|
+
**************************************************************************************/
|
|
260
|
+
|
|
261
|
+
IndexProductResidualQuantizerFastScan::IndexProductResidualQuantizerFastScan(
|
|
262
|
+
int d, ///< dimensionality of the input vectors
|
|
263
|
+
size_t nsplits, ///< number of residual quantizers
|
|
264
|
+
size_t Msub, ///< number of subquantizers per RQ
|
|
265
|
+
size_t nbits, ///< number of bit per subvector index
|
|
266
|
+
MetricType metric,
|
|
267
|
+
Search_type_t search_type,
|
|
268
|
+
int bbs)
|
|
269
|
+
: prq(d, nsplits, Msub, nbits, search_type) {
|
|
270
|
+
init(&prq, metric, bbs);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
IndexProductResidualQuantizerFastScan::IndexProductResidualQuantizerFastScan() {
|
|
274
|
+
aq = &prq;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**************************************************************************************
|
|
278
|
+
* IndexProductLocalSearchQuantizerFastScan
|
|
279
|
+
**************************************************************************************/
|
|
280
|
+
|
|
281
|
+
IndexProductLocalSearchQuantizerFastScan::
|
|
282
|
+
IndexProductLocalSearchQuantizerFastScan(
|
|
283
|
+
int d, ///< dimensionality of the input vectors
|
|
284
|
+
size_t nsplits, ///< number of local search quantizers
|
|
285
|
+
size_t Msub, ///< number of subquantizers per LSQ
|
|
286
|
+
size_t nbits, ///< number of bit per subvector index
|
|
287
|
+
MetricType metric,
|
|
288
|
+
Search_type_t search_type,
|
|
289
|
+
int bbs)
|
|
290
|
+
: plsq(d, nsplits, Msub, nbits, search_type) {
|
|
291
|
+
init(&plsq, metric, bbs);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
IndexProductLocalSearchQuantizerFastScan::
|
|
295
|
+
IndexProductLocalSearchQuantizerFastScan() {
|
|
296
|
+
aq = &plsq;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
} // namespace faiss
|