faiss 0.3.0 → 0.3.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 +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/ext/faiss/extconf.rb +9 -2
- data/ext/faiss/index.cpp +1 -1
- data/ext/faiss/index_binary.cpp +2 -2
- data/ext/faiss/product_quantizer.cpp +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +7 -7
- data/vendor/faiss/faiss/AutoTune.h +1 -2
- data/vendor/faiss/faiss/Clustering.cpp +39 -22
- data/vendor/faiss/faiss/Clustering.h +40 -21
- data/vendor/faiss/faiss/IVFlib.cpp +26 -12
- data/vendor/faiss/faiss/Index.cpp +1 -1
- data/vendor/faiss/faiss/Index.h +40 -10
- data/vendor/faiss/faiss/Index2Layer.cpp +7 -7
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +176 -166
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +15 -15
- data/vendor/faiss/faiss/IndexBinary.cpp +9 -4
- data/vendor/faiss/faiss/IndexBinary.h +8 -19
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +2 -1
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +24 -31
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +25 -50
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +107 -188
- data/vendor/faiss/faiss/IndexFastScan.cpp +95 -146
- data/vendor/faiss/faiss/IndexFastScan.h +9 -8
- data/vendor/faiss/faiss/IndexFlat.cpp +206 -10
- data/vendor/faiss/faiss/IndexFlat.h +20 -1
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +170 -5
- data/vendor/faiss/faiss/IndexFlatCodes.h +23 -4
- data/vendor/faiss/faiss/IndexHNSW.cpp +231 -382
- data/vendor/faiss/faiss/IndexHNSW.h +62 -49
- data/vendor/faiss/faiss/IndexIDMap.cpp +69 -28
- data/vendor/faiss/faiss/IndexIDMap.h +24 -2
- data/vendor/faiss/faiss/IndexIVF.cpp +162 -56
- data/vendor/faiss/faiss/IndexIVF.h +46 -6
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +33 -26
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +6 -2
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +19 -46
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -3
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +502 -401
- data/vendor/faiss/faiss/IndexIVFFastScan.h +63 -26
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +15 -5
- data/vendor/faiss/faiss/IndexIVFFlat.h +3 -2
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +172 -0
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.h +56 -0
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +79 -125
- data/vendor/faiss/faiss/IndexIVFPQ.h +6 -7
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +39 -52
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +4 -3
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +45 -29
- data/vendor/faiss/faiss/IndexIVFPQR.h +5 -2
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +25 -27
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +6 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +14 -16
- data/vendor/faiss/faiss/IndexLattice.cpp +1 -19
- data/vendor/faiss/faiss/IndexLattice.h +3 -22
- data/vendor/faiss/faiss/IndexNNDescent.cpp +3 -33
- data/vendor/faiss/faiss/IndexNNDescent.h +1 -1
- data/vendor/faiss/faiss/IndexNSG.cpp +11 -27
- data/vendor/faiss/faiss/IndexNSG.h +11 -11
- data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
- data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
- data/vendor/faiss/faiss/IndexPQ.cpp +72 -88
- data/vendor/faiss/faiss/IndexPQ.h +1 -4
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +1 -1
- data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -31
- data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +54 -24
- data/vendor/faiss/faiss/IndexRefine.h +7 -0
- data/vendor/faiss/faiss/IndexReplicas.cpp +23 -26
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +25 -17
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +6 -4
- data/vendor/faiss/faiss/IndexShards.cpp +21 -29
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +1 -2
- data/vendor/faiss/faiss/MatrixStats.cpp +17 -32
- data/vendor/faiss/faiss/MatrixStats.h +21 -9
- data/vendor/faiss/faiss/MetaIndexes.cpp +35 -35
- data/vendor/faiss/faiss/MetricType.h +7 -2
- data/vendor/faiss/faiss/VectorTransform.cpp +13 -26
- data/vendor/faiss/faiss/VectorTransform.h +7 -7
- data/vendor/faiss/faiss/clone_index.cpp +15 -10
- data/vendor/faiss/faiss/clone_index.h +3 -0
- data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +95 -17
- data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +152 -0
- data/vendor/faiss/faiss/cppcontrib/factory_tools.h +24 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +83 -30
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +123 -8
- data/vendor/faiss/faiss/gpu/GpuCloner.h +22 -0
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +13 -0
- data/vendor/faiss/faiss/gpu/GpuDistance.h +46 -38
- data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -1
- data/vendor/faiss/faiss/gpu/GpuIndex.h +30 -12
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +282 -0
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +4 -4
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +14 -9
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +20 -3
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -11
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +1 -3
- data/vendor/faiss/faiss/gpu/GpuResources.cpp +24 -3
- data/vendor/faiss/faiss/gpu/GpuResources.h +39 -11
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +142 -17
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +57 -3
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +26 -21
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +7 -1
- data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +8 -5
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +25 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +129 -9
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +332 -40
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +299 -208
- data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +1 -0
- data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
- data/vendor/faiss/faiss/gpu/utils/RaftUtils.h +75 -0
- data/vendor/faiss/faiss/gpu/utils/Timer.cpp +4 -1
- data/vendor/faiss/faiss/gpu/utils/Timer.h +1 -1
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +3 -1
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +5 -5
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +26 -1
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +10 -3
- data/vendor/faiss/faiss/impl/DistanceComputer.h +70 -1
- data/vendor/faiss/faiss/impl/FaissAssert.h +4 -2
- data/vendor/faiss/faiss/impl/FaissException.h +13 -34
- data/vendor/faiss/faiss/impl/HNSW.cpp +605 -186
- data/vendor/faiss/faiss/impl/HNSW.h +52 -30
- data/vendor/faiss/faiss/impl/IDSelector.h +4 -4
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +11 -9
- data/vendor/faiss/faiss/impl/LookupTableScaler.h +34 -0
- data/vendor/faiss/faiss/impl/NNDescent.cpp +42 -27
- data/vendor/faiss/faiss/impl/NSG.cpp +0 -29
- data/vendor/faiss/faiss/impl/NSG.h +1 -1
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +14 -12
- data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +1 -1
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +25 -22
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +6 -2
- data/vendor/faiss/faiss/impl/Quantizer.h +1 -1
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +27 -1015
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +5 -63
- data/vendor/faiss/faiss/impl/ResultHandler.h +347 -172
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +1104 -147
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +3 -8
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +285 -42
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +21 -14
- data/vendor/faiss/faiss/impl/code_distance/code_distance.h +22 -12
- data/vendor/faiss/faiss/impl/index_read.cpp +74 -34
- data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
- data/vendor/faiss/faiss/impl/index_write.cpp +88 -51
- data/vendor/faiss/faiss/impl/io.cpp +23 -15
- data/vendor/faiss/faiss/impl/io.h +4 -4
- data/vendor/faiss/faiss/impl/io_macros.h +6 -0
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
- data/vendor/faiss/faiss/impl/platform_macros.h +40 -1
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +14 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +7 -6
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +52 -38
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +487 -49
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +960 -0
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +176 -0
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +481 -225
- data/vendor/faiss/faiss/index_factory.cpp +41 -20
- data/vendor/faiss/faiss/index_io.h +12 -5
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +28 -8
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +3 -0
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +10 -2
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +73 -17
- data/vendor/faiss/faiss/invlists/InvertedLists.h +26 -8
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +24 -9
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +2 -1
- data/vendor/faiss/faiss/python/python_callbacks.cpp +4 -4
- data/vendor/faiss/faiss/utils/Heap.cpp +3 -1
- data/vendor/faiss/faiss/utils/Heap.h +105 -0
- data/vendor/faiss/faiss/utils/NeuralNet.cpp +342 -0
- data/vendor/faiss/faiss/utils/NeuralNet.h +147 -0
- data/vendor/faiss/faiss/utils/WorkerThread.h +1 -0
- data/vendor/faiss/faiss/utils/bf16.h +36 -0
- data/vendor/faiss/faiss/utils/distances.cpp +147 -123
- data/vendor/faiss/faiss/utils/distances.h +86 -9
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +5 -5
- data/vendor/faiss/faiss/utils/distances_fused/avx512.h +2 -2
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +2 -2
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +1 -1
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +5 -5
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +1 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +1589 -243
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +70 -0
- data/vendor/faiss/faiss/utils/extra_distances.cpp +85 -137
- data/vendor/faiss/faiss/utils/extra_distances.h +3 -2
- data/vendor/faiss/faiss/utils/fp16-arm.h +29 -0
- data/vendor/faiss/faiss/utils/fp16.h +2 -0
- data/vendor/faiss/faiss/utils/hamming.cpp +163 -111
- data/vendor/faiss/faiss/utils/hamming.h +58 -0
- data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +16 -89
- data/vendor/faiss/faiss/utils/hamming_distance/common.h +1 -0
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +19 -88
- data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +58 -0
- data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +14 -104
- data/vendor/faiss/faiss/utils/partitioning.cpp +3 -4
- data/vendor/faiss/faiss/utils/prefetch.h +77 -0
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +0 -14
- data/vendor/faiss/faiss/utils/random.cpp +43 -0
- data/vendor/faiss/faiss/utils/random.h +25 -0
- data/vendor/faiss/faiss/utils/simdlib.h +10 -1
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +0 -6
- data/vendor/faiss/faiss/utils/simdlib_avx512.h +296 -0
- data/vendor/faiss/faiss/utils/simdlib_neon.h +77 -79
- data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
- data/vendor/faiss/faiss/utils/sorting.cpp +140 -5
- data/vendor/faiss/faiss/utils/sorting.h +27 -0
- data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
- data/vendor/faiss/faiss/utils/utils.cpp +120 -7
- data/vendor/faiss/faiss/utils/utils.h +60 -20
- metadata +23 -4
- data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +0 -102
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
namespace faiss {
|
|
16
16
|
|
|
17
|
+
struct NormTableScaler;
|
|
18
|
+
struct SIMDResultHandlerToFloat;
|
|
19
|
+
|
|
17
20
|
/** Fast scan version of IVFPQ and IVFAQ. Works for 4-bit PQ/AQ for now.
|
|
18
21
|
*
|
|
19
22
|
* The codes in the inverted lists are not stored sequentially but
|
|
@@ -28,6 +31,12 @@ namespace faiss {
|
|
|
28
31
|
* 11: idem, collect results in reservoir
|
|
29
32
|
* 12: optimizer int16 search, collect results in heap, uses qbs
|
|
30
33
|
* 13: idem, collect results in reservoir
|
|
34
|
+
* 14: internally multithreaded implem over nq * nprobe
|
|
35
|
+
* 15: same with reservoir
|
|
36
|
+
*
|
|
37
|
+
* For range search, only 10 and 12 are supported.
|
|
38
|
+
* add 100 to the implem to force single-thread scanning (the coarse quantizer
|
|
39
|
+
* may still use multiple threads).
|
|
31
40
|
*/
|
|
32
41
|
|
|
33
42
|
struct IndexIVFFastScan : IndexIVF {
|
|
@@ -45,7 +54,6 @@ struct IndexIVFFastScan : IndexIVF {
|
|
|
45
54
|
int implem = 0;
|
|
46
55
|
// skip some parts of the computation (for timing)
|
|
47
56
|
int skip = 0;
|
|
48
|
-
bool by_residual = false;
|
|
49
57
|
|
|
50
58
|
// batching factors at search time (0 = default)
|
|
51
59
|
int qbs = 0;
|
|
@@ -81,19 +89,24 @@ struct IndexIVFFastScan : IndexIVF {
|
|
|
81
89
|
|
|
82
90
|
virtual bool lookup_table_is_3d() const = 0;
|
|
83
91
|
|
|
92
|
+
// compact way of conveying coarse quantization results
|
|
93
|
+
struct CoarseQuantized {
|
|
94
|
+
size_t nprobe;
|
|
95
|
+
const float* dis = nullptr;
|
|
96
|
+
const idx_t* ids = nullptr;
|
|
97
|
+
};
|
|
98
|
+
|
|
84
99
|
virtual void compute_LUT(
|
|
85
100
|
size_t n,
|
|
86
101
|
const float* x,
|
|
87
|
-
const
|
|
88
|
-
const float* coarse_dis,
|
|
102
|
+
const CoarseQuantized& cq,
|
|
89
103
|
AlignedTable<float>& dis_tables,
|
|
90
104
|
AlignedTable<float>& biases) const = 0;
|
|
91
105
|
|
|
92
106
|
void compute_LUT_uint8(
|
|
93
107
|
size_t n,
|
|
94
108
|
const float* x,
|
|
95
|
-
const
|
|
96
|
-
const float* coarse_dis,
|
|
109
|
+
const CoarseQuantized& cq,
|
|
97
110
|
AlignedTable<uint8_t>& dis_tables,
|
|
98
111
|
AlignedTable<uint16_t>& biases,
|
|
99
112
|
float* normalizers) const;
|
|
@@ -106,7 +119,18 @@ struct IndexIVFFastScan : IndexIVF {
|
|
|
106
119
|
idx_t* labels,
|
|
107
120
|
const SearchParameters* params = nullptr) const override;
|
|
108
121
|
|
|
109
|
-
|
|
122
|
+
void search_preassigned(
|
|
123
|
+
idx_t n,
|
|
124
|
+
const float* x,
|
|
125
|
+
idx_t k,
|
|
126
|
+
const idx_t* assign,
|
|
127
|
+
const float* centroid_dis,
|
|
128
|
+
float* distances,
|
|
129
|
+
idx_t* labels,
|
|
130
|
+
bool store_pairs,
|
|
131
|
+
const IVFSearchParameters* params = nullptr,
|
|
132
|
+
IndexIVFStats* stats = nullptr) const override;
|
|
133
|
+
|
|
110
134
|
void range_search(
|
|
111
135
|
idx_t n,
|
|
112
136
|
const float* x,
|
|
@@ -116,69 +140,82 @@ struct IndexIVFFastScan : IndexIVF {
|
|
|
116
140
|
|
|
117
141
|
// internal search funcs
|
|
118
142
|
|
|
119
|
-
|
|
143
|
+
// dispatch to implementations and parallelize
|
|
120
144
|
void search_dispatch_implem(
|
|
121
145
|
idx_t n,
|
|
122
146
|
const float* x,
|
|
123
147
|
idx_t k,
|
|
124
148
|
float* distances,
|
|
125
149
|
idx_t* labels,
|
|
126
|
-
const
|
|
150
|
+
const CoarseQuantized& cq,
|
|
151
|
+
const NormTableScaler* scaler,
|
|
152
|
+
const IVFSearchParameters* params = nullptr) const;
|
|
127
153
|
|
|
128
|
-
|
|
154
|
+
void range_search_dispatch_implem(
|
|
155
|
+
idx_t n,
|
|
156
|
+
const float* x,
|
|
157
|
+
float radius,
|
|
158
|
+
RangeSearchResult& rres,
|
|
159
|
+
const CoarseQuantized& cq_in,
|
|
160
|
+
const NormTableScaler* scaler,
|
|
161
|
+
const IVFSearchParameters* params = nullptr) const;
|
|
162
|
+
|
|
163
|
+
// impl 1 and 2 are just for verification
|
|
164
|
+
template <class C>
|
|
129
165
|
void search_implem_1(
|
|
130
166
|
idx_t n,
|
|
131
167
|
const float* x,
|
|
132
168
|
idx_t k,
|
|
133
169
|
float* distances,
|
|
134
170
|
idx_t* labels,
|
|
135
|
-
const
|
|
171
|
+
const CoarseQuantized& cq,
|
|
172
|
+
const NormTableScaler* scaler,
|
|
173
|
+
const IVFSearchParameters* params = nullptr) const;
|
|
136
174
|
|
|
137
|
-
template <class C
|
|
175
|
+
template <class C>
|
|
138
176
|
void search_implem_2(
|
|
139
177
|
idx_t n,
|
|
140
178
|
const float* x,
|
|
141
179
|
idx_t k,
|
|
142
180
|
float* distances,
|
|
143
181
|
idx_t* labels,
|
|
144
|
-
const
|
|
182
|
+
const CoarseQuantized& cq,
|
|
183
|
+
const NormTableScaler* scaler,
|
|
184
|
+
const IVFSearchParameters* params = nullptr) const;
|
|
145
185
|
|
|
146
186
|
// implem 10 and 12 are not multithreaded internally, so
|
|
147
187
|
// export search stats
|
|
148
|
-
template <class C, class Scaler>
|
|
149
188
|
void search_implem_10(
|
|
150
189
|
idx_t n,
|
|
151
190
|
const float* x,
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
idx_t* labels,
|
|
155
|
-
int impl,
|
|
191
|
+
SIMDResultHandlerToFloat& handler,
|
|
192
|
+
const CoarseQuantized& cq,
|
|
156
193
|
size_t* ndis_out,
|
|
157
194
|
size_t* nlist_out,
|
|
158
|
-
const
|
|
195
|
+
const NormTableScaler* scaler,
|
|
196
|
+
const IVFSearchParameters* params = nullptr) const;
|
|
159
197
|
|
|
160
|
-
template <class C, class Scaler>
|
|
161
198
|
void search_implem_12(
|
|
162
199
|
idx_t n,
|
|
163
200
|
const float* x,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
idx_t* labels,
|
|
167
|
-
int impl,
|
|
201
|
+
SIMDResultHandlerToFloat& handler,
|
|
202
|
+
const CoarseQuantized& cq,
|
|
168
203
|
size_t* ndis_out,
|
|
169
204
|
size_t* nlist_out,
|
|
170
|
-
const
|
|
205
|
+
const NormTableScaler* scaler,
|
|
206
|
+
const IVFSearchParameters* params = nullptr) const;
|
|
171
207
|
|
|
172
208
|
// implem 14 is multithreaded internally across nprobes and queries
|
|
173
|
-
template <class C, class Scaler>
|
|
174
209
|
void search_implem_14(
|
|
175
210
|
idx_t n,
|
|
176
211
|
const float* x,
|
|
177
212
|
idx_t k,
|
|
178
213
|
float* distances,
|
|
179
214
|
idx_t* labels,
|
|
215
|
+
const CoarseQuantized& cq,
|
|
180
216
|
int impl,
|
|
181
|
-
const
|
|
217
|
+
const NormTableScaler* scaler,
|
|
218
|
+
const IVFSearchParameters* params = nullptr) const;
|
|
182
219
|
|
|
183
220
|
// reconstruct vectors from packed invlists
|
|
184
221
|
void reconstruct_from_offset(int64_t list_no, int64_t offset, float* recons)
|
|
@@ -36,15 +36,22 @@ IndexIVFFlat::IndexIVFFlat(
|
|
|
36
36
|
MetricType metric)
|
|
37
37
|
: IndexIVF(quantizer, d, nlist, sizeof(float) * d, metric) {
|
|
38
38
|
code_size = sizeof(float) * d;
|
|
39
|
+
by_residual = false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
IndexIVFFlat::IndexIVFFlat() {
|
|
43
|
+
by_residual = false;
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
void IndexIVFFlat::add_core(
|
|
42
47
|
idx_t n,
|
|
43
48
|
const float* x,
|
|
44
|
-
const
|
|
45
|
-
const
|
|
49
|
+
const idx_t* xids,
|
|
50
|
+
const idx_t* coarse_idx,
|
|
51
|
+
void* inverted_list_context) {
|
|
46
52
|
FAISS_THROW_IF_NOT(is_trained);
|
|
47
53
|
FAISS_THROW_IF_NOT(coarse_idx);
|
|
54
|
+
FAISS_THROW_IF_NOT(!by_residual);
|
|
48
55
|
assert(invlists);
|
|
49
56
|
direct_map.check_can_add(xids);
|
|
50
57
|
|
|
@@ -64,8 +71,8 @@ void IndexIVFFlat::add_core(
|
|
|
64
71
|
if (list_no >= 0 && list_no % nt == rank) {
|
|
65
72
|
idx_t id = xids ? xids[i] : ntotal + i;
|
|
66
73
|
const float* xi = x + i * d;
|
|
67
|
-
size_t offset =
|
|
68
|
-
|
|
74
|
+
size_t offset = invlists->add_entry(
|
|
75
|
+
list_no, id, (const uint8_t*)xi, inverted_list_context);
|
|
69
76
|
dm_adder.add(i, list_no, offset);
|
|
70
77
|
n_add++;
|
|
71
78
|
} else if (rank == 0 && list_no == -1) {
|
|
@@ -89,6 +96,7 @@ void IndexIVFFlat::encode_vectors(
|
|
|
89
96
|
const idx_t* list_nos,
|
|
90
97
|
uint8_t* codes,
|
|
91
98
|
bool include_listnos) const {
|
|
99
|
+
FAISS_THROW_IF_NOT(!by_residual);
|
|
92
100
|
if (!include_listnos) {
|
|
93
101
|
memcpy(codes, x, code_size * n);
|
|
94
102
|
} else {
|
|
@@ -123,7 +131,9 @@ struct IVFFlatScanner : InvertedListScanner {
|
|
|
123
131
|
size_t d;
|
|
124
132
|
|
|
125
133
|
IVFFlatScanner(size_t d, bool store_pairs, const IDSelector* sel)
|
|
126
|
-
: InvertedListScanner(store_pairs, sel), d(d) {
|
|
134
|
+
: InvertedListScanner(store_pairs, sel), d(d) {
|
|
135
|
+
keep_max = is_similarity_metric(metric);
|
|
136
|
+
}
|
|
127
137
|
|
|
128
138
|
const float* xi;
|
|
129
139
|
void set_query(const float* query) override {
|
|
@@ -32,7 +32,8 @@ struct IndexIVFFlat : IndexIVF {
|
|
|
32
32
|
idx_t n,
|
|
33
33
|
const float* x,
|
|
34
34
|
const idx_t* xids,
|
|
35
|
-
const idx_t* precomputed_idx
|
|
35
|
+
const idx_t* precomputed_idx,
|
|
36
|
+
void* inverted_list_context = nullptr) override;
|
|
36
37
|
|
|
37
38
|
void encode_vectors(
|
|
38
39
|
idx_t n,
|
|
@@ -50,7 +51,7 @@ struct IndexIVFFlat : IndexIVF {
|
|
|
50
51
|
|
|
51
52
|
void sa_decode(idx_t n, const uint8_t* bytes, float* x) const override;
|
|
52
53
|
|
|
53
|
-
IndexIVFFlat()
|
|
54
|
+
IndexIVFFlat();
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
struct IndexIVFFlatDedup : IndexIVFFlat {
|
|
@@ -0,0 +1,172 @@
|
|
|
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/IndexIVFIndependentQuantizer.h>
|
|
9
|
+
#include <faiss/IndexIVFPQ.h>
|
|
10
|
+
#include <faiss/impl/FaissAssert.h>
|
|
11
|
+
#include <faiss/utils/utils.h>
|
|
12
|
+
|
|
13
|
+
namespace faiss {
|
|
14
|
+
|
|
15
|
+
IndexIVFIndependentQuantizer::IndexIVFIndependentQuantizer(
|
|
16
|
+
Index* quantizer,
|
|
17
|
+
IndexIVF* index_ivf,
|
|
18
|
+
VectorTransform* vt)
|
|
19
|
+
: Index(quantizer->d, index_ivf->metric_type),
|
|
20
|
+
quantizer(quantizer),
|
|
21
|
+
vt(vt),
|
|
22
|
+
index_ivf(index_ivf) {
|
|
23
|
+
if (vt) {
|
|
24
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
25
|
+
vt->d_in == d && vt->d_out == index_ivf->d,
|
|
26
|
+
"invalid vector dimensions");
|
|
27
|
+
} else {
|
|
28
|
+
FAISS_THROW_IF_NOT_MSG(index_ivf->d == d, "invalid vector dimensions");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (quantizer->is_trained && quantizer->ntotal != 0) {
|
|
32
|
+
FAISS_THROW_IF_NOT(quantizer->ntotal == index_ivf->nlist);
|
|
33
|
+
}
|
|
34
|
+
if (index_ivf->is_trained && vt) {
|
|
35
|
+
FAISS_THROW_IF_NOT(vt->is_trained);
|
|
36
|
+
}
|
|
37
|
+
ntotal = index_ivf->ntotal;
|
|
38
|
+
is_trained =
|
|
39
|
+
(quantizer->is_trained && quantizer->ntotal == index_ivf->nlist &&
|
|
40
|
+
(!vt || vt->is_trained) && index_ivf->is_trained);
|
|
41
|
+
|
|
42
|
+
// disable precomputed tables because they use the distances that are
|
|
43
|
+
// provided by the coarse quantizer (that are out of sync with the IVFPQ)
|
|
44
|
+
if (auto index_ivfpq = dynamic_cast<IndexIVFPQ*>(index_ivf)) {
|
|
45
|
+
index_ivfpq->use_precomputed_table = -1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
IndexIVFIndependentQuantizer::~IndexIVFIndependentQuantizer() {
|
|
50
|
+
if (own_fields) {
|
|
51
|
+
delete quantizer;
|
|
52
|
+
delete index_ivf;
|
|
53
|
+
delete vt;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
namespace {
|
|
58
|
+
|
|
59
|
+
struct VTransformedVectors : TransformedVectors {
|
|
60
|
+
VTransformedVectors(const VectorTransform* vt, idx_t n, const float* x)
|
|
61
|
+
: TransformedVectors(x, vt ? vt->apply(n, x) : x) {}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
struct SubsampledVectors : TransformedVectors {
|
|
65
|
+
SubsampledVectors(int d, idx_t* n, idx_t max_n, const float* x)
|
|
66
|
+
: TransformedVectors(
|
|
67
|
+
x,
|
|
68
|
+
fvecs_maybe_subsample(d, (size_t*)n, max_n, x, true)) {}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
} // anonymous namespace
|
|
72
|
+
|
|
73
|
+
void IndexIVFIndependentQuantizer::add(idx_t n, const float* x) {
|
|
74
|
+
std::vector<float> D(n);
|
|
75
|
+
std::vector<idx_t> I(n);
|
|
76
|
+
quantizer->search(n, x, 1, D.data(), I.data());
|
|
77
|
+
|
|
78
|
+
VTransformedVectors tv(vt, n, x);
|
|
79
|
+
|
|
80
|
+
index_ivf->add_core(n, tv.x, nullptr, I.data());
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void IndexIVFIndependentQuantizer::search(
|
|
84
|
+
idx_t n,
|
|
85
|
+
const float* x,
|
|
86
|
+
idx_t k,
|
|
87
|
+
float* distances,
|
|
88
|
+
idx_t* labels,
|
|
89
|
+
const SearchParameters* params) const {
|
|
90
|
+
FAISS_THROW_IF_NOT_MSG(!params, "search parameters not supported");
|
|
91
|
+
int nprobe = index_ivf->nprobe;
|
|
92
|
+
std::vector<float> D(n * nprobe);
|
|
93
|
+
std::vector<idx_t> I(n * nprobe);
|
|
94
|
+
quantizer->search(n, x, nprobe, D.data(), I.data());
|
|
95
|
+
|
|
96
|
+
VTransformedVectors tv(vt, n, x);
|
|
97
|
+
|
|
98
|
+
index_ivf->search_preassigned(
|
|
99
|
+
n, tv.x, k, I.data(), D.data(), distances, labels, false);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void IndexIVFIndependentQuantizer::reset() {
|
|
103
|
+
index_ivf->reset();
|
|
104
|
+
ntotal = 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
void IndexIVFIndependentQuantizer::train(idx_t n, const float* x) {
|
|
108
|
+
// quantizer training
|
|
109
|
+
size_t nlist = index_ivf->nlist;
|
|
110
|
+
Level1Quantizer l1(quantizer, nlist);
|
|
111
|
+
l1.train_q1(n, x, verbose, metric_type);
|
|
112
|
+
|
|
113
|
+
// train the VectorTransform
|
|
114
|
+
if (vt && !vt->is_trained) {
|
|
115
|
+
if (verbose) {
|
|
116
|
+
printf("IndexIVFIndependentQuantizer: train the VectorTransform\n");
|
|
117
|
+
}
|
|
118
|
+
vt->train(n, x);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// get the centroids from the quantizer, transform them and
|
|
122
|
+
// add them to the index_ivf's quantizer
|
|
123
|
+
if (verbose) {
|
|
124
|
+
printf("IndexIVFIndependentQuantizer: extract the main quantizer centroids\n");
|
|
125
|
+
}
|
|
126
|
+
std::vector<float> centroids(nlist * d);
|
|
127
|
+
quantizer->reconstruct_n(0, nlist, centroids.data());
|
|
128
|
+
VTransformedVectors tcent(vt, nlist, centroids.data());
|
|
129
|
+
|
|
130
|
+
if (verbose) {
|
|
131
|
+
printf("IndexIVFIndependentQuantizer: add centroids to the secondary quantizer\n");
|
|
132
|
+
}
|
|
133
|
+
if (!index_ivf->quantizer->is_trained) {
|
|
134
|
+
index_ivf->quantizer->train(nlist, tcent.x);
|
|
135
|
+
}
|
|
136
|
+
index_ivf->quantizer->add(nlist, tcent.x);
|
|
137
|
+
|
|
138
|
+
// train the payload
|
|
139
|
+
|
|
140
|
+
// optional subsampling
|
|
141
|
+
idx_t max_nt = index_ivf->train_encoder_num_vectors();
|
|
142
|
+
if (max_nt <= 0) {
|
|
143
|
+
max_nt = (size_t)1 << 35;
|
|
144
|
+
}
|
|
145
|
+
SubsampledVectors sv(index_ivf->d, &n, max_nt, x);
|
|
146
|
+
|
|
147
|
+
// transform subsampled vectors
|
|
148
|
+
VTransformedVectors tv(vt, n, sv.x);
|
|
149
|
+
|
|
150
|
+
if (verbose) {
|
|
151
|
+
printf("IndexIVFIndependentQuantizer: train encoder\n");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (index_ivf->by_residual) {
|
|
155
|
+
// assign with quantizer
|
|
156
|
+
std::vector<idx_t> assign(n);
|
|
157
|
+
quantizer->assign(n, sv.x, assign.data());
|
|
158
|
+
|
|
159
|
+
// compute residual with IVF quantizer
|
|
160
|
+
std::vector<float> residuals(n * index_ivf->d);
|
|
161
|
+
index_ivf->quantizer->compute_residual_n(
|
|
162
|
+
n, tv.x, residuals.data(), assign.data());
|
|
163
|
+
|
|
164
|
+
index_ivf->train_encoder(n, residuals.data(), assign.data());
|
|
165
|
+
} else {
|
|
166
|
+
index_ivf->train_encoder(n, tv.x, nullptr);
|
|
167
|
+
}
|
|
168
|
+
index_ivf->is_trained = true;
|
|
169
|
+
is_trained = true;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
} // namespace faiss
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <faiss/IndexIVF.h>
|
|
11
|
+
#include <faiss/VectorTransform.h>
|
|
12
|
+
|
|
13
|
+
namespace faiss {
|
|
14
|
+
|
|
15
|
+
/** An IVF index with a quantizer that has a different input dimension from the
|
|
16
|
+
* payload size. The vectors to encode are obtained from the input vectors by a
|
|
17
|
+
* VectorTransform.
|
|
18
|
+
*/
|
|
19
|
+
struct IndexIVFIndependentQuantizer : Index {
|
|
20
|
+
/// quantizer is fed directly with the input vectors
|
|
21
|
+
Index* quantizer = nullptr;
|
|
22
|
+
|
|
23
|
+
/// transform before the IVF vectors are applied
|
|
24
|
+
VectorTransform* vt = nullptr;
|
|
25
|
+
|
|
26
|
+
/// the IVF index, controls nlist and nprobe
|
|
27
|
+
IndexIVF* index_ivf = nullptr;
|
|
28
|
+
|
|
29
|
+
/// whether *this owns the 3 fields
|
|
30
|
+
bool own_fields = false;
|
|
31
|
+
|
|
32
|
+
IndexIVFIndependentQuantizer(
|
|
33
|
+
Index* quantizer,
|
|
34
|
+
IndexIVF* index_ivf,
|
|
35
|
+
VectorTransform* vt = nullptr);
|
|
36
|
+
|
|
37
|
+
IndexIVFIndependentQuantizer() {}
|
|
38
|
+
|
|
39
|
+
void train(idx_t n, const float* x) override;
|
|
40
|
+
|
|
41
|
+
void add(idx_t n, const float* x) override;
|
|
42
|
+
|
|
43
|
+
void search(
|
|
44
|
+
idx_t n,
|
|
45
|
+
const float* x,
|
|
46
|
+
idx_t k,
|
|
47
|
+
float* distances,
|
|
48
|
+
idx_t* labels,
|
|
49
|
+
const SearchParameters* params = nullptr) const override;
|
|
50
|
+
|
|
51
|
+
void reset() override;
|
|
52
|
+
|
|
53
|
+
~IndexIVFIndependentQuantizer() override;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
} // namespace faiss
|