faiss 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +103 -3
- data/ext/faiss/ext.cpp +99 -32
- data/ext/faiss/extconf.rb +12 -2
- data/lib/faiss/ext.bundle +0 -0
- data/lib/faiss/index.rb +3 -3
- data/lib/faiss/index_binary.rb +3 -3
- data/lib/faiss/kmeans.rb +1 -1
- data/lib/faiss/pca_matrix.rb +2 -2
- data/lib/faiss/product_quantizer.rb +3 -3
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/AutoTune.cpp +719 -0
- data/vendor/faiss/AutoTune.h +212 -0
- data/vendor/faiss/Clustering.cpp +261 -0
- data/vendor/faiss/Clustering.h +101 -0
- data/vendor/faiss/IVFlib.cpp +339 -0
- data/vendor/faiss/IVFlib.h +132 -0
- data/vendor/faiss/Index.cpp +171 -0
- data/vendor/faiss/Index.h +261 -0
- data/vendor/faiss/Index2Layer.cpp +437 -0
- data/vendor/faiss/Index2Layer.h +85 -0
- data/vendor/faiss/IndexBinary.cpp +77 -0
- data/vendor/faiss/IndexBinary.h +163 -0
- data/vendor/faiss/IndexBinaryFlat.cpp +83 -0
- data/vendor/faiss/IndexBinaryFlat.h +54 -0
- data/vendor/faiss/IndexBinaryFromFloat.cpp +78 -0
- data/vendor/faiss/IndexBinaryFromFloat.h +52 -0
- data/vendor/faiss/IndexBinaryHNSW.cpp +325 -0
- data/vendor/faiss/IndexBinaryHNSW.h +56 -0
- data/vendor/faiss/IndexBinaryIVF.cpp +671 -0
- data/vendor/faiss/IndexBinaryIVF.h +211 -0
- data/vendor/faiss/IndexFlat.cpp +508 -0
- data/vendor/faiss/IndexFlat.h +175 -0
- data/vendor/faiss/IndexHNSW.cpp +1090 -0
- data/vendor/faiss/IndexHNSW.h +170 -0
- data/vendor/faiss/IndexIVF.cpp +909 -0
- data/vendor/faiss/IndexIVF.h +353 -0
- data/vendor/faiss/IndexIVFFlat.cpp +502 -0
- data/vendor/faiss/IndexIVFFlat.h +118 -0
- data/vendor/faiss/IndexIVFPQ.cpp +1207 -0
- data/vendor/faiss/IndexIVFPQ.h +161 -0
- data/vendor/faiss/IndexIVFPQR.cpp +219 -0
- data/vendor/faiss/IndexIVFPQR.h +65 -0
- data/vendor/faiss/IndexIVFSpectralHash.cpp +331 -0
- data/vendor/faiss/IndexIVFSpectralHash.h +75 -0
- data/vendor/faiss/IndexLSH.cpp +225 -0
- data/vendor/faiss/IndexLSH.h +87 -0
- data/vendor/faiss/IndexLattice.cpp +143 -0
- data/vendor/faiss/IndexLattice.h +68 -0
- data/vendor/faiss/IndexPQ.cpp +1188 -0
- data/vendor/faiss/IndexPQ.h +199 -0
- data/vendor/faiss/IndexPreTransform.cpp +288 -0
- data/vendor/faiss/IndexPreTransform.h +91 -0
- data/vendor/faiss/IndexReplicas.cpp +123 -0
- data/vendor/faiss/IndexReplicas.h +76 -0
- data/vendor/faiss/IndexScalarQuantizer.cpp +317 -0
- data/vendor/faiss/IndexScalarQuantizer.h +127 -0
- data/vendor/faiss/IndexShards.cpp +317 -0
- data/vendor/faiss/IndexShards.h +100 -0
- data/vendor/faiss/InvertedLists.cpp +623 -0
- data/vendor/faiss/InvertedLists.h +334 -0
- data/vendor/faiss/LICENSE +21 -0
- data/vendor/faiss/MatrixStats.cpp +252 -0
- data/vendor/faiss/MatrixStats.h +62 -0
- data/vendor/faiss/MetaIndexes.cpp +351 -0
- data/vendor/faiss/MetaIndexes.h +126 -0
- data/vendor/faiss/OnDiskInvertedLists.cpp +674 -0
- data/vendor/faiss/OnDiskInvertedLists.h +127 -0
- data/vendor/faiss/VectorTransform.cpp +1157 -0
- data/vendor/faiss/VectorTransform.h +322 -0
- data/vendor/faiss/c_api/AutoTune_c.cpp +83 -0
- data/vendor/faiss/c_api/AutoTune_c.h +64 -0
- data/vendor/faiss/c_api/Clustering_c.cpp +139 -0
- data/vendor/faiss/c_api/Clustering_c.h +117 -0
- data/vendor/faiss/c_api/IndexFlat_c.cpp +140 -0
- data/vendor/faiss/c_api/IndexFlat_c.h +115 -0
- data/vendor/faiss/c_api/IndexIVFFlat_c.cpp +64 -0
- data/vendor/faiss/c_api/IndexIVFFlat_c.h +58 -0
- data/vendor/faiss/c_api/IndexIVF_c.cpp +92 -0
- data/vendor/faiss/c_api/IndexIVF_c.h +135 -0
- data/vendor/faiss/c_api/IndexLSH_c.cpp +37 -0
- data/vendor/faiss/c_api/IndexLSH_c.h +40 -0
- data/vendor/faiss/c_api/IndexShards_c.cpp +44 -0
- data/vendor/faiss/c_api/IndexShards_c.h +42 -0
- data/vendor/faiss/c_api/Index_c.cpp +105 -0
- data/vendor/faiss/c_api/Index_c.h +183 -0
- data/vendor/faiss/c_api/MetaIndexes_c.cpp +49 -0
- data/vendor/faiss/c_api/MetaIndexes_c.h +49 -0
- data/vendor/faiss/c_api/clone_index_c.cpp +23 -0
- data/vendor/faiss/c_api/clone_index_c.h +32 -0
- data/vendor/faiss/c_api/error_c.h +42 -0
- data/vendor/faiss/c_api/error_impl.cpp +27 -0
- data/vendor/faiss/c_api/error_impl.h +16 -0
- data/vendor/faiss/c_api/faiss_c.h +58 -0
- data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +96 -0
- data/vendor/faiss/c_api/gpu/GpuAutoTune_c.h +56 -0
- data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +52 -0
- data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.h +68 -0
- data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +17 -0
- data/vendor/faiss/c_api/gpu/GpuIndex_c.h +30 -0
- data/vendor/faiss/c_api/gpu/GpuIndicesOptions_c.h +38 -0
- data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +86 -0
- data/vendor/faiss/c_api/gpu/GpuResources_c.h +66 -0
- data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +54 -0
- data/vendor/faiss/c_api/gpu/StandardGpuResources_c.h +53 -0
- data/vendor/faiss/c_api/gpu/macros_impl.h +42 -0
- data/vendor/faiss/c_api/impl/AuxIndexStructures_c.cpp +220 -0
- data/vendor/faiss/c_api/impl/AuxIndexStructures_c.h +149 -0
- data/vendor/faiss/c_api/index_factory_c.cpp +26 -0
- data/vendor/faiss/c_api/index_factory_c.h +30 -0
- data/vendor/faiss/c_api/index_io_c.cpp +42 -0
- data/vendor/faiss/c_api/index_io_c.h +50 -0
- data/vendor/faiss/c_api/macros_impl.h +110 -0
- data/vendor/faiss/clone_index.cpp +147 -0
- data/vendor/faiss/clone_index.h +38 -0
- data/vendor/faiss/demos/demo_imi_flat.cpp +151 -0
- data/vendor/faiss/demos/demo_imi_pq.cpp +199 -0
- data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +146 -0
- data/vendor/faiss/demos/demo_sift1M.cpp +252 -0
- data/vendor/faiss/gpu/GpuAutoTune.cpp +95 -0
- data/vendor/faiss/gpu/GpuAutoTune.h +27 -0
- data/vendor/faiss/gpu/GpuCloner.cpp +403 -0
- data/vendor/faiss/gpu/GpuCloner.h +82 -0
- data/vendor/faiss/gpu/GpuClonerOptions.cpp +28 -0
- data/vendor/faiss/gpu/GpuClonerOptions.h +53 -0
- data/vendor/faiss/gpu/GpuDistance.h +52 -0
- data/vendor/faiss/gpu/GpuFaissAssert.h +29 -0
- data/vendor/faiss/gpu/GpuIndex.h +148 -0
- data/vendor/faiss/gpu/GpuIndexBinaryFlat.h +89 -0
- data/vendor/faiss/gpu/GpuIndexFlat.h +190 -0
- data/vendor/faiss/gpu/GpuIndexIVF.h +89 -0
- data/vendor/faiss/gpu/GpuIndexIVFFlat.h +85 -0
- data/vendor/faiss/gpu/GpuIndexIVFPQ.h +143 -0
- data/vendor/faiss/gpu/GpuIndexIVFScalarQuantizer.h +100 -0
- data/vendor/faiss/gpu/GpuIndicesOptions.h +30 -0
- data/vendor/faiss/gpu/GpuResources.cpp +52 -0
- data/vendor/faiss/gpu/GpuResources.h +73 -0
- data/vendor/faiss/gpu/StandardGpuResources.cpp +295 -0
- data/vendor/faiss/gpu/StandardGpuResources.h +114 -0
- data/vendor/faiss/gpu/impl/RemapIndices.cpp +43 -0
- data/vendor/faiss/gpu/impl/RemapIndices.h +24 -0
- data/vendor/faiss/gpu/perf/IndexWrapper-inl.h +71 -0
- data/vendor/faiss/gpu/perf/IndexWrapper.h +39 -0
- data/vendor/faiss/gpu/perf/PerfClustering.cpp +115 -0
- data/vendor/faiss/gpu/perf/PerfIVFPQAdd.cpp +139 -0
- data/vendor/faiss/gpu/perf/WriteIndex.cpp +102 -0
- data/vendor/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +130 -0
- data/vendor/faiss/gpu/test/TestGpuIndexFlat.cpp +371 -0
- data/vendor/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +550 -0
- data/vendor/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +450 -0
- data/vendor/faiss/gpu/test/TestGpuMemoryException.cpp +84 -0
- data/vendor/faiss/gpu/test/TestUtils.cpp +315 -0
- data/vendor/faiss/gpu/test/TestUtils.h +93 -0
- data/vendor/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +159 -0
- data/vendor/faiss/gpu/utils/DeviceMemory.cpp +77 -0
- data/vendor/faiss/gpu/utils/DeviceMemory.h +71 -0
- data/vendor/faiss/gpu/utils/DeviceUtils.h +185 -0
- data/vendor/faiss/gpu/utils/MemorySpace.cpp +89 -0
- data/vendor/faiss/gpu/utils/MemorySpace.h +44 -0
- data/vendor/faiss/gpu/utils/StackDeviceMemory.cpp +239 -0
- data/vendor/faiss/gpu/utils/StackDeviceMemory.h +129 -0
- data/vendor/faiss/gpu/utils/StaticUtils.h +83 -0
- data/vendor/faiss/gpu/utils/Timer.cpp +60 -0
- data/vendor/faiss/gpu/utils/Timer.h +52 -0
- data/vendor/faiss/impl/AuxIndexStructures.cpp +305 -0
- data/vendor/faiss/impl/AuxIndexStructures.h +246 -0
- data/vendor/faiss/impl/FaissAssert.h +95 -0
- data/vendor/faiss/impl/FaissException.cpp +66 -0
- data/vendor/faiss/impl/FaissException.h +71 -0
- data/vendor/faiss/impl/HNSW.cpp +818 -0
- data/vendor/faiss/impl/HNSW.h +275 -0
- data/vendor/faiss/impl/PolysemousTraining.cpp +953 -0
- data/vendor/faiss/impl/PolysemousTraining.h +158 -0
- data/vendor/faiss/impl/ProductQuantizer.cpp +876 -0
- data/vendor/faiss/impl/ProductQuantizer.h +242 -0
- data/vendor/faiss/impl/ScalarQuantizer.cpp +1628 -0
- data/vendor/faiss/impl/ScalarQuantizer.h +120 -0
- data/vendor/faiss/impl/ThreadedIndex-inl.h +192 -0
- data/vendor/faiss/impl/ThreadedIndex.h +80 -0
- data/vendor/faiss/impl/index_read.cpp +793 -0
- data/vendor/faiss/impl/index_write.cpp +558 -0
- data/vendor/faiss/impl/io.cpp +142 -0
- data/vendor/faiss/impl/io.h +98 -0
- data/vendor/faiss/impl/lattice_Zn.cpp +712 -0
- data/vendor/faiss/impl/lattice_Zn.h +199 -0
- data/vendor/faiss/index_factory.cpp +392 -0
- data/vendor/faiss/index_factory.h +25 -0
- data/vendor/faiss/index_io.h +75 -0
- data/vendor/faiss/misc/test_blas.cpp +84 -0
- data/vendor/faiss/tests/test_binary_flat.cpp +64 -0
- data/vendor/faiss/tests/test_dealloc_invlists.cpp +183 -0
- data/vendor/faiss/tests/test_ivfpq_codec.cpp +67 -0
- data/vendor/faiss/tests/test_ivfpq_indexing.cpp +98 -0
- data/vendor/faiss/tests/test_lowlevel_ivf.cpp +566 -0
- data/vendor/faiss/tests/test_merge.cpp +258 -0
- data/vendor/faiss/tests/test_omp_threads.cpp +14 -0
- data/vendor/faiss/tests/test_ondisk_ivf.cpp +220 -0
- data/vendor/faiss/tests/test_pairs_decoding.cpp +189 -0
- data/vendor/faiss/tests/test_params_override.cpp +231 -0
- data/vendor/faiss/tests/test_pq_encoding.cpp +98 -0
- data/vendor/faiss/tests/test_sliding_ivf.cpp +240 -0
- data/vendor/faiss/tests/test_threaded_index.cpp +253 -0
- data/vendor/faiss/tests/test_transfer_invlists.cpp +159 -0
- data/vendor/faiss/tutorial/cpp/1-Flat.cpp +98 -0
- data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +81 -0
- data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +93 -0
- data/vendor/faiss/tutorial/cpp/4-GPU.cpp +119 -0
- data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +99 -0
- data/vendor/faiss/utils/Heap.cpp +122 -0
- data/vendor/faiss/utils/Heap.h +495 -0
- data/vendor/faiss/utils/WorkerThread.cpp +126 -0
- data/vendor/faiss/utils/WorkerThread.h +61 -0
- data/vendor/faiss/utils/distances.cpp +765 -0
- data/vendor/faiss/utils/distances.h +243 -0
- data/vendor/faiss/utils/distances_simd.cpp +809 -0
- data/vendor/faiss/utils/extra_distances.cpp +336 -0
- data/vendor/faiss/utils/extra_distances.h +54 -0
- data/vendor/faiss/utils/hamming-inl.h +472 -0
- data/vendor/faiss/utils/hamming.cpp +792 -0
- data/vendor/faiss/utils/hamming.h +220 -0
- data/vendor/faiss/utils/random.cpp +192 -0
- data/vendor/faiss/utils/random.h +60 -0
- data/vendor/faiss/utils/utils.cpp +783 -0
- data/vendor/faiss/utils/utils.h +181 -0
- metadata +216 -2
|
@@ -0,0 +1,199 @@
|
|
|
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
|
+
// -*- c++ -*-
|
|
9
|
+
#ifndef FAISS_LATTICE_ZN_H
|
|
10
|
+
#define FAISS_LATTICE_ZN_H
|
|
11
|
+
|
|
12
|
+
#include <vector>
|
|
13
|
+
#include <stddef.h>
|
|
14
|
+
#include <stdint.h>
|
|
15
|
+
|
|
16
|
+
namespace faiss {
|
|
17
|
+
|
|
18
|
+
/** returns the nearest vertex in the sphere to a query. Returns only
|
|
19
|
+
* the coordinates, not an id.
|
|
20
|
+
*
|
|
21
|
+
* Algorithm: all points are derived from a one atom vector up to a
|
|
22
|
+
* permutation and sign changes. The search function finds the most
|
|
23
|
+
* appropriate atom and transformation.
|
|
24
|
+
*/
|
|
25
|
+
struct ZnSphereSearch {
|
|
26
|
+
int dimS, r2;
|
|
27
|
+
int natom;
|
|
28
|
+
|
|
29
|
+
/// size dim * ntatom
|
|
30
|
+
std::vector<float> voc;
|
|
31
|
+
|
|
32
|
+
ZnSphereSearch(int dim, int r2);
|
|
33
|
+
|
|
34
|
+
/// find nearest centroid. x does not need to be normalized
|
|
35
|
+
float search(const float *x, float *c) const;
|
|
36
|
+
|
|
37
|
+
/// full call. Requires externally-allocated temp space
|
|
38
|
+
float search(const float *x, float *c,
|
|
39
|
+
float *tmp, // size 2 *dim
|
|
40
|
+
int *tmp_int, // size dim
|
|
41
|
+
int *ibest_out = nullptr
|
|
42
|
+
) const;
|
|
43
|
+
|
|
44
|
+
// multi-threaded
|
|
45
|
+
void search_multi(int n, const float *x,
|
|
46
|
+
float *c_out,
|
|
47
|
+
float *dp_out);
|
|
48
|
+
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
/***************************************************************************
|
|
53
|
+
* Support ids as well.
|
|
54
|
+
*
|
|
55
|
+
* Limitations: ids are limited to 64 bit
|
|
56
|
+
***************************************************************************/
|
|
57
|
+
|
|
58
|
+
struct EnumeratedVectors {
|
|
59
|
+
/// size of the collection
|
|
60
|
+
uint64_t nv;
|
|
61
|
+
int dim;
|
|
62
|
+
|
|
63
|
+
explicit EnumeratedVectors(int dim): nv(0), dim(dim) {}
|
|
64
|
+
|
|
65
|
+
/// encode a vector from a collection
|
|
66
|
+
virtual uint64_t encode(const float *x) const = 0;
|
|
67
|
+
|
|
68
|
+
/// decode it
|
|
69
|
+
virtual void decode(uint64_t code, float *c) const = 0;
|
|
70
|
+
|
|
71
|
+
// call encode on nc vectors
|
|
72
|
+
void encode_multi (size_t nc, const float *c,
|
|
73
|
+
uint64_t * codes) const;
|
|
74
|
+
|
|
75
|
+
// call decode on nc codes
|
|
76
|
+
void decode_multi (size_t nc, const uint64_t * codes,
|
|
77
|
+
float *c) const;
|
|
78
|
+
|
|
79
|
+
// find the nearest neighbor of each xq
|
|
80
|
+
// (decodes and computes distances)
|
|
81
|
+
void find_nn (size_t n, const uint64_t * codes,
|
|
82
|
+
size_t nq, const float *xq,
|
|
83
|
+
long *idx, float *dis);
|
|
84
|
+
|
|
85
|
+
virtual ~EnumeratedVectors() {}
|
|
86
|
+
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
struct Repeat {
|
|
90
|
+
float val;
|
|
91
|
+
int n;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/** Repeats: used to encode a vector that has n occurrences of
|
|
95
|
+
* val. Encodes the signs and permutation of the vector. Useful for
|
|
96
|
+
* atoms.
|
|
97
|
+
*/
|
|
98
|
+
struct Repeats {
|
|
99
|
+
int dim;
|
|
100
|
+
std::vector<Repeat> repeats;
|
|
101
|
+
|
|
102
|
+
// initialize from a template of the atom.
|
|
103
|
+
Repeats(int dim = 0, const float *c = nullptr);
|
|
104
|
+
|
|
105
|
+
// count number of possible codes for this atom
|
|
106
|
+
long count() const;
|
|
107
|
+
|
|
108
|
+
long encode(const float *c) const;
|
|
109
|
+
|
|
110
|
+
void decode(uint64_t code, float *c) const;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
/** codec that can return ids for the encoded vectors
|
|
115
|
+
*
|
|
116
|
+
* uses the ZnSphereSearch to encode the vector by encoding the
|
|
117
|
+
* permutation and signs. Depends on ZnSphereSearch because it uses
|
|
118
|
+
* the atom numbers */
|
|
119
|
+
struct ZnSphereCodec: ZnSphereSearch, EnumeratedVectors {
|
|
120
|
+
|
|
121
|
+
struct CodeSegment:Repeats {
|
|
122
|
+
explicit CodeSegment(const Repeats & r): Repeats(r) {}
|
|
123
|
+
uint64_t c0; // first code assigned to segment
|
|
124
|
+
int signbits;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
std::vector<CodeSegment> code_segments;
|
|
128
|
+
uint64_t nv;
|
|
129
|
+
size_t code_size;
|
|
130
|
+
|
|
131
|
+
ZnSphereCodec(int dim, int r2);
|
|
132
|
+
|
|
133
|
+
uint64_t search_and_encode(const float *x) const;
|
|
134
|
+
|
|
135
|
+
void decode(uint64_t code, float *c) const override;
|
|
136
|
+
|
|
137
|
+
/// takes vectors that do not need to be centroids
|
|
138
|
+
uint64_t encode(const float *x) const override;
|
|
139
|
+
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/** recursive sphere codec
|
|
143
|
+
*
|
|
144
|
+
* Uses a recursive decomposition on the dimensions to encode
|
|
145
|
+
* centroids found by the ZnSphereSearch. The codes are *not*
|
|
146
|
+
* compatible with the ones of ZnSpehreCodec
|
|
147
|
+
*/
|
|
148
|
+
struct ZnSphereCodecRec: EnumeratedVectors {
|
|
149
|
+
|
|
150
|
+
int r2;
|
|
151
|
+
|
|
152
|
+
int log2_dim;
|
|
153
|
+
int code_size;
|
|
154
|
+
|
|
155
|
+
ZnSphereCodecRec(int dim, int r2);
|
|
156
|
+
|
|
157
|
+
uint64_t encode_centroid(const float *c) const;
|
|
158
|
+
|
|
159
|
+
void decode(uint64_t code, float *c) const override;
|
|
160
|
+
|
|
161
|
+
/// vectors need to be centroids (does not work on arbitrary
|
|
162
|
+
/// vectors)
|
|
163
|
+
uint64_t encode(const float *x) const override;
|
|
164
|
+
|
|
165
|
+
std::vector<uint64_t> all_nv;
|
|
166
|
+
std::vector<uint64_t> all_nv_cum;
|
|
167
|
+
|
|
168
|
+
int decode_cache_ld;
|
|
169
|
+
std::vector<std::vector<float> > decode_cache;
|
|
170
|
+
|
|
171
|
+
// nb of vectors in the sphere in dim 2^ld with r2 radius
|
|
172
|
+
uint64_t get_nv(int ld, int r2a) const;
|
|
173
|
+
|
|
174
|
+
// cumulative version
|
|
175
|
+
uint64_t get_nv_cum(int ld, int r2t, int r2a) const;
|
|
176
|
+
void set_nv_cum(int ld, int r2t, int r2a, uint64_t v);
|
|
177
|
+
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
/** Codec that uses the recursive codec if dim is a power of 2 and
|
|
182
|
+
* the regular one otherwise */
|
|
183
|
+
struct ZnSphereCodecAlt: ZnSphereCodec {
|
|
184
|
+
bool use_rec;
|
|
185
|
+
ZnSphereCodecRec znc_rec;
|
|
186
|
+
|
|
187
|
+
ZnSphereCodecAlt (int dim, int r2);
|
|
188
|
+
|
|
189
|
+
uint64_t encode(const float *x) const override;
|
|
190
|
+
|
|
191
|
+
void decode(uint64_t code, float *c) const override;
|
|
192
|
+
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
#endif
|
|
@@ -0,0 +1,392 @@
|
|
|
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
|
+
// -*- c++ -*-
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* implementation of Hyper-parameter auto-tuning
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#include <faiss/AutoTune.h>
|
|
15
|
+
|
|
16
|
+
#include <cmath>
|
|
17
|
+
#include <stdarg.h> /* va_list, va_start, va_arg, va_end */
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
#include <faiss/impl/FaissAssert.h>
|
|
21
|
+
#include <faiss/utils/utils.h>
|
|
22
|
+
#include <faiss/utils/random.h>
|
|
23
|
+
|
|
24
|
+
#include <faiss/IndexFlat.h>
|
|
25
|
+
#include <faiss/VectorTransform.h>
|
|
26
|
+
#include <faiss/IndexPreTransform.h>
|
|
27
|
+
#include <faiss/IndexLSH.h>
|
|
28
|
+
#include <faiss/IndexPQ.h>
|
|
29
|
+
#include <faiss/IndexIVF.h>
|
|
30
|
+
#include <faiss/IndexIVFPQ.h>
|
|
31
|
+
#include <faiss/IndexIVFPQR.h>
|
|
32
|
+
#include <faiss/Index2Layer.h>
|
|
33
|
+
#include <faiss/IndexIVFFlat.h>
|
|
34
|
+
#include <faiss/MetaIndexes.h>
|
|
35
|
+
#include <faiss/IndexScalarQuantizer.h>
|
|
36
|
+
#include <faiss/IndexHNSW.h>
|
|
37
|
+
#include <faiss/IndexLattice.h>
|
|
38
|
+
|
|
39
|
+
#include <faiss/IndexBinaryFlat.h>
|
|
40
|
+
#include <faiss/IndexBinaryHNSW.h>
|
|
41
|
+
#include <faiss/IndexBinaryIVF.h>
|
|
42
|
+
|
|
43
|
+
namespace faiss {
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
/***************************************************************
|
|
47
|
+
* index_factory
|
|
48
|
+
***************************************************************/
|
|
49
|
+
|
|
50
|
+
namespace {
|
|
51
|
+
|
|
52
|
+
struct VTChain {
|
|
53
|
+
std::vector<VectorTransform *> chain;
|
|
54
|
+
~VTChain () {
|
|
55
|
+
for (int i = 0; i < chain.size(); i++) {
|
|
56
|
+
delete chain[i];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/// what kind of training does this coarse quantizer require?
|
|
63
|
+
char get_trains_alone(const Index *coarse_quantizer) {
|
|
64
|
+
return
|
|
65
|
+
dynamic_cast<const MultiIndexQuantizer*>(coarse_quantizer) ? 1 :
|
|
66
|
+
dynamic_cast<const IndexHNSWFlat*>(coarse_quantizer) ? 2 :
|
|
67
|
+
0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
Index *index_factory (int d, const char *description_in, MetricType metric)
|
|
74
|
+
{
|
|
75
|
+
FAISS_THROW_IF_NOT(metric == METRIC_L2 ||
|
|
76
|
+
metric == METRIC_INNER_PRODUCT);
|
|
77
|
+
VTChain vts;
|
|
78
|
+
Index *coarse_quantizer = nullptr;
|
|
79
|
+
Index *index = nullptr;
|
|
80
|
+
bool add_idmap = false;
|
|
81
|
+
bool make_IndexRefineFlat = false;
|
|
82
|
+
|
|
83
|
+
ScopeDeleter1<Index> del_coarse_quantizer, del_index;
|
|
84
|
+
|
|
85
|
+
char description[strlen(description_in) + 1];
|
|
86
|
+
char *ptr;
|
|
87
|
+
memcpy (description, description_in, strlen(description_in) + 1);
|
|
88
|
+
|
|
89
|
+
int64_t ncentroids = -1;
|
|
90
|
+
bool use_2layer = false;
|
|
91
|
+
|
|
92
|
+
for (char *tok = strtok_r (description, " ,", &ptr);
|
|
93
|
+
tok;
|
|
94
|
+
tok = strtok_r (nullptr, " ,", &ptr)) {
|
|
95
|
+
int d_out, opq_M, nbit, M, M2, pq_m, ncent, r2;
|
|
96
|
+
std::string stok(tok);
|
|
97
|
+
nbit = 8;
|
|
98
|
+
|
|
99
|
+
// to avoid mem leaks with exceptions:
|
|
100
|
+
// do all tests before any instanciation
|
|
101
|
+
|
|
102
|
+
VectorTransform *vt_1 = nullptr;
|
|
103
|
+
Index *coarse_quantizer_1 = nullptr;
|
|
104
|
+
Index *index_1 = nullptr;
|
|
105
|
+
|
|
106
|
+
// VectorTransforms
|
|
107
|
+
if (sscanf (tok, "PCA%d", &d_out) == 1) {
|
|
108
|
+
vt_1 = new PCAMatrix (d, d_out);
|
|
109
|
+
d = d_out;
|
|
110
|
+
} else if (sscanf (tok, "PCAR%d", &d_out) == 1) {
|
|
111
|
+
vt_1 = new PCAMatrix (d, d_out, 0, true);
|
|
112
|
+
d = d_out;
|
|
113
|
+
} else if (sscanf (tok, "RR%d", &d_out) == 1) {
|
|
114
|
+
vt_1 = new RandomRotationMatrix (d, d_out);
|
|
115
|
+
d = d_out;
|
|
116
|
+
} else if (sscanf (tok, "PCAW%d", &d_out) == 1) {
|
|
117
|
+
vt_1 = new PCAMatrix (d, d_out, -0.5, false);
|
|
118
|
+
d = d_out;
|
|
119
|
+
} else if (sscanf (tok, "PCAWR%d", &d_out) == 1) {
|
|
120
|
+
vt_1 = new PCAMatrix (d, d_out, -0.5, true);
|
|
121
|
+
d = d_out;
|
|
122
|
+
} else if (sscanf (tok, "OPQ%d_%d", &opq_M, &d_out) == 2) {
|
|
123
|
+
vt_1 = new OPQMatrix (d, opq_M, d_out);
|
|
124
|
+
d = d_out;
|
|
125
|
+
} else if (sscanf (tok, "OPQ%d", &opq_M) == 1) {
|
|
126
|
+
vt_1 = new OPQMatrix (d, opq_M);
|
|
127
|
+
} else if (sscanf (tok, "ITQ%d", &d_out) == 1) {
|
|
128
|
+
vt_1 = new ITQTransform (d, d_out, true);
|
|
129
|
+
d = d_out;
|
|
130
|
+
} else if (stok == "ITQ") {
|
|
131
|
+
vt_1 = new ITQTransform (d, d, false);
|
|
132
|
+
} else if (sscanf (tok, "Pad%d", &d_out) == 1) {
|
|
133
|
+
if (d_out > d) {
|
|
134
|
+
vt_1 = new RemapDimensionsTransform (d, d_out, false);
|
|
135
|
+
d = d_out;
|
|
136
|
+
}
|
|
137
|
+
} else if (stok == "L2norm") {
|
|
138
|
+
vt_1 = new NormalizationTransform (d, 2.0);
|
|
139
|
+
|
|
140
|
+
// coarse quantizers
|
|
141
|
+
} else if (!coarse_quantizer &&
|
|
142
|
+
sscanf (tok, "IVF%ld_HNSW%d", &ncentroids, &M) == 2) {
|
|
143
|
+
FAISS_THROW_IF_NOT (metric == METRIC_L2);
|
|
144
|
+
coarse_quantizer_1 = new IndexHNSWFlat (d, M);
|
|
145
|
+
|
|
146
|
+
} else if (!coarse_quantizer &&
|
|
147
|
+
sscanf (tok, "IVF%ld", &ncentroids) == 1) {
|
|
148
|
+
if (metric == METRIC_L2) {
|
|
149
|
+
coarse_quantizer_1 = new IndexFlatL2 (d);
|
|
150
|
+
} else {
|
|
151
|
+
coarse_quantizer_1 = new IndexFlatIP (d);
|
|
152
|
+
}
|
|
153
|
+
} else if (!coarse_quantizer && sscanf (tok, "IMI2x%d", &nbit) == 1) {
|
|
154
|
+
FAISS_THROW_IF_NOT_MSG (metric == METRIC_L2,
|
|
155
|
+
"MultiIndex not implemented for inner prod search");
|
|
156
|
+
coarse_quantizer_1 = new MultiIndexQuantizer (d, 2, nbit);
|
|
157
|
+
ncentroids = 1 << (2 * nbit);
|
|
158
|
+
|
|
159
|
+
} else if (!coarse_quantizer &&
|
|
160
|
+
sscanf (tok, "Residual%dx%d", &M, &nbit) == 2) {
|
|
161
|
+
FAISS_THROW_IF_NOT_MSG (metric == METRIC_L2,
|
|
162
|
+
"MultiIndex not implemented for inner prod search");
|
|
163
|
+
coarse_quantizer_1 = new MultiIndexQuantizer (d, M, nbit);
|
|
164
|
+
ncentroids = int64_t(1) << (M * nbit);
|
|
165
|
+
use_2layer = true;
|
|
166
|
+
|
|
167
|
+
} else if (!coarse_quantizer &&
|
|
168
|
+
sscanf (tok, "Residual%ld", &ncentroids) == 1) {
|
|
169
|
+
coarse_quantizer_1 = new IndexFlatL2 (d);
|
|
170
|
+
use_2layer = true;
|
|
171
|
+
|
|
172
|
+
} else if (stok == "IDMap") {
|
|
173
|
+
add_idmap = true;
|
|
174
|
+
|
|
175
|
+
// IVFs
|
|
176
|
+
} else if (!index && (stok == "Flat" || stok == "FlatDedup")) {
|
|
177
|
+
if (coarse_quantizer) {
|
|
178
|
+
// if there was an IVF in front, then it is an IVFFlat
|
|
179
|
+
IndexIVF *index_ivf = stok == "Flat" ?
|
|
180
|
+
new IndexIVFFlat (
|
|
181
|
+
coarse_quantizer, d, ncentroids, metric) :
|
|
182
|
+
new IndexIVFFlatDedup (
|
|
183
|
+
coarse_quantizer, d, ncentroids, metric);
|
|
184
|
+
index_ivf->quantizer_trains_alone =
|
|
185
|
+
get_trains_alone (coarse_quantizer);
|
|
186
|
+
index_ivf->cp.spherical = metric == METRIC_INNER_PRODUCT;
|
|
187
|
+
del_coarse_quantizer.release ();
|
|
188
|
+
index_ivf->own_fields = true;
|
|
189
|
+
index_1 = index_ivf;
|
|
190
|
+
} else {
|
|
191
|
+
FAISS_THROW_IF_NOT_MSG (stok != "FlatDedup",
|
|
192
|
+
"dedup supported only for IVFFlat");
|
|
193
|
+
index_1 = new IndexFlat (d, metric);
|
|
194
|
+
}
|
|
195
|
+
} else if (!index && (stok == "SQ8" || stok == "SQ4" || stok == "SQ6" ||
|
|
196
|
+
stok == "SQfp16")) {
|
|
197
|
+
ScalarQuantizer::QuantizerType qt =
|
|
198
|
+
stok == "SQ8" ? ScalarQuantizer::QT_8bit :
|
|
199
|
+
stok == "SQ6" ? ScalarQuantizer::QT_6bit :
|
|
200
|
+
stok == "SQ4" ? ScalarQuantizer::QT_4bit :
|
|
201
|
+
stok == "SQfp16" ? ScalarQuantizer::QT_fp16 :
|
|
202
|
+
ScalarQuantizer::QT_4bit;
|
|
203
|
+
if (coarse_quantizer) {
|
|
204
|
+
FAISS_THROW_IF_NOT (!use_2layer);
|
|
205
|
+
IndexIVFScalarQuantizer *index_ivf =
|
|
206
|
+
new IndexIVFScalarQuantizer (
|
|
207
|
+
coarse_quantizer, d, ncentroids, qt, metric);
|
|
208
|
+
index_ivf->quantizer_trains_alone =
|
|
209
|
+
get_trains_alone (coarse_quantizer);
|
|
210
|
+
del_coarse_quantizer.release ();
|
|
211
|
+
index_ivf->own_fields = true;
|
|
212
|
+
index_1 = index_ivf;
|
|
213
|
+
} else {
|
|
214
|
+
index_1 = new IndexScalarQuantizer (d, qt, metric);
|
|
215
|
+
}
|
|
216
|
+
} else if (!index && sscanf (tok, "PQ%d+%d", &M, &M2) == 2) {
|
|
217
|
+
FAISS_THROW_IF_NOT_MSG(coarse_quantizer,
|
|
218
|
+
"PQ with + works only with an IVF");
|
|
219
|
+
FAISS_THROW_IF_NOT_MSG(metric == METRIC_L2,
|
|
220
|
+
"IVFPQR not implemented for inner product search");
|
|
221
|
+
IndexIVFPQR *index_ivf = new IndexIVFPQR (
|
|
222
|
+
coarse_quantizer, d, ncentroids, M, 8, M2, 8);
|
|
223
|
+
index_ivf->quantizer_trains_alone =
|
|
224
|
+
get_trains_alone (coarse_quantizer);
|
|
225
|
+
del_coarse_quantizer.release ();
|
|
226
|
+
index_ivf->own_fields = true;
|
|
227
|
+
index_1 = index_ivf;
|
|
228
|
+
} else if (!index && (sscanf (tok, "PQ%dx%d", &M, &nbit) == 2 ||
|
|
229
|
+
sscanf (tok, "PQ%d", &M) == 1 ||
|
|
230
|
+
sscanf (tok, "PQ%dnp", &M) == 1)) {
|
|
231
|
+
bool do_polysemous_training = stok.find("np") == std::string::npos;
|
|
232
|
+
if (coarse_quantizer) {
|
|
233
|
+
if (!use_2layer) {
|
|
234
|
+
IndexIVFPQ *index_ivf = new IndexIVFPQ (
|
|
235
|
+
coarse_quantizer, d, ncentroids, M, nbit);
|
|
236
|
+
index_ivf->quantizer_trains_alone =
|
|
237
|
+
get_trains_alone (coarse_quantizer);
|
|
238
|
+
index_ivf->metric_type = metric;
|
|
239
|
+
index_ivf->cp.spherical = metric == METRIC_INNER_PRODUCT;
|
|
240
|
+
del_coarse_quantizer.release ();
|
|
241
|
+
index_ivf->own_fields = true;
|
|
242
|
+
index_ivf->do_polysemous_training = do_polysemous_training;
|
|
243
|
+
index_1 = index_ivf;
|
|
244
|
+
} else {
|
|
245
|
+
Index2Layer *index_2l = new Index2Layer
|
|
246
|
+
(coarse_quantizer, ncentroids, M, nbit);
|
|
247
|
+
index_2l->q1.quantizer_trains_alone =
|
|
248
|
+
get_trains_alone (coarse_quantizer);
|
|
249
|
+
index_2l->q1.own_fields = true;
|
|
250
|
+
index_1 = index_2l;
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
IndexPQ *index_pq = new IndexPQ (d, M, nbit, metric);
|
|
254
|
+
index_pq->do_polysemous_training = do_polysemous_training;
|
|
255
|
+
index_1 = index_pq;
|
|
256
|
+
}
|
|
257
|
+
} else if (!index &&
|
|
258
|
+
sscanf (tok, "HNSW%d_%d+PQ%d", &M, &ncent, &pq_m) == 3) {
|
|
259
|
+
Index * quant = new IndexFlatL2 (d);
|
|
260
|
+
IndexHNSW2Level * hidx2l = new IndexHNSW2Level (quant, ncent, pq_m, M);
|
|
261
|
+
Index2Layer * idx2l = dynamic_cast<Index2Layer*>(hidx2l->storage);
|
|
262
|
+
idx2l->q1.own_fields = true;
|
|
263
|
+
index_1 = hidx2l;
|
|
264
|
+
} else if (!index &&
|
|
265
|
+
sscanf (tok, "HNSW%d_2x%d+PQ%d", &M, &nbit, &pq_m) == 3) {
|
|
266
|
+
Index * quant = new MultiIndexQuantizer (d, 2, nbit);
|
|
267
|
+
IndexHNSW2Level * hidx2l =
|
|
268
|
+
new IndexHNSW2Level (quant, 1 << (2 * nbit), pq_m, M);
|
|
269
|
+
Index2Layer * idx2l = dynamic_cast<Index2Layer*>(hidx2l->storage);
|
|
270
|
+
idx2l->q1.own_fields = true;
|
|
271
|
+
idx2l->q1.quantizer_trains_alone = 1;
|
|
272
|
+
index_1 = hidx2l;
|
|
273
|
+
} else if (!index &&
|
|
274
|
+
sscanf (tok, "HNSW%d_PQ%d", &M, &pq_m) == 2) {
|
|
275
|
+
index_1 = new IndexHNSWPQ (d, pq_m, M);
|
|
276
|
+
} else if (!index &&
|
|
277
|
+
sscanf (tok, "HNSW%d", &M) == 1) {
|
|
278
|
+
index_1 = new IndexHNSWFlat (d, M);
|
|
279
|
+
} else if (!index &&
|
|
280
|
+
sscanf (tok, "HNSW%d_SQ%d", &M, &pq_m) == 2 &&
|
|
281
|
+
pq_m == 8) {
|
|
282
|
+
index_1 = new IndexHNSWSQ (d, ScalarQuantizer::QT_8bit, M);
|
|
283
|
+
} else if (!index && (stok == "LSH" || stok == "LSHr" ||
|
|
284
|
+
stok == "LSHrt" || stok == "LSHt")) {
|
|
285
|
+
bool rotate_data = strstr(tok, "r") != nullptr;
|
|
286
|
+
bool train_thresholds = strstr(tok, "t") != nullptr;
|
|
287
|
+
index_1 = new IndexLSH (d, d, rotate_data, train_thresholds);
|
|
288
|
+
} else if (!index &&
|
|
289
|
+
sscanf (tok, "ZnLattice%dx%d_%d", &M, &r2, &nbit) == 3) {
|
|
290
|
+
FAISS_THROW_IF_NOT(!coarse_quantizer);
|
|
291
|
+
index_1 = new IndexLattice(d, M, nbit, r2);
|
|
292
|
+
} else if (stok == "RFlat") {
|
|
293
|
+
make_IndexRefineFlat = true;
|
|
294
|
+
} else {
|
|
295
|
+
FAISS_THROW_FMT( "could not parse token \"%s\" in %s\n",
|
|
296
|
+
tok, description_in);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (index_1 && add_idmap) {
|
|
300
|
+
IndexIDMap *idmap = new IndexIDMap(index_1);
|
|
301
|
+
del_index.set (idmap);
|
|
302
|
+
idmap->own_fields = true;
|
|
303
|
+
index_1 = idmap;
|
|
304
|
+
add_idmap = false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (vt_1) {
|
|
308
|
+
vts.chain.push_back (vt_1);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (coarse_quantizer_1) {
|
|
312
|
+
coarse_quantizer = coarse_quantizer_1;
|
|
313
|
+
del_coarse_quantizer.set (coarse_quantizer);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (index_1) {
|
|
317
|
+
index = index_1;
|
|
318
|
+
del_index.set (index);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
FAISS_THROW_IF_NOT_FMT(index, "description %s did not generate an index",
|
|
323
|
+
description_in);
|
|
324
|
+
|
|
325
|
+
// nothing can go wrong now
|
|
326
|
+
del_index.release ();
|
|
327
|
+
del_coarse_quantizer.release ();
|
|
328
|
+
|
|
329
|
+
if (add_idmap) {
|
|
330
|
+
fprintf(stderr, "index_factory: WARNING: "
|
|
331
|
+
"IDMap option not used\n");
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (vts.chain.size() > 0) {
|
|
335
|
+
IndexPreTransform *index_pt = new IndexPreTransform (index);
|
|
336
|
+
index_pt->own_fields = true;
|
|
337
|
+
// add from back
|
|
338
|
+
while (vts.chain.size() > 0) {
|
|
339
|
+
index_pt->prepend_transform (vts.chain.back ());
|
|
340
|
+
vts.chain.pop_back ();
|
|
341
|
+
}
|
|
342
|
+
index = index_pt;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (make_IndexRefineFlat) {
|
|
346
|
+
IndexRefineFlat *index_rf = new IndexRefineFlat (index);
|
|
347
|
+
index_rf->own_fields = true;
|
|
348
|
+
index = index_rf;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return index;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
IndexBinary *index_binary_factory(int d, const char *description)
|
|
355
|
+
{
|
|
356
|
+
IndexBinary *index = nullptr;
|
|
357
|
+
|
|
358
|
+
int ncentroids = -1;
|
|
359
|
+
int M;
|
|
360
|
+
|
|
361
|
+
if (sscanf(description, "BIVF%d_HNSW%d", &ncentroids, &M) == 2) {
|
|
362
|
+
IndexBinaryIVF *index_ivf = new IndexBinaryIVF(
|
|
363
|
+
new IndexBinaryHNSW(d, M), d, ncentroids
|
|
364
|
+
);
|
|
365
|
+
index_ivf->own_fields = true;
|
|
366
|
+
index = index_ivf;
|
|
367
|
+
|
|
368
|
+
} else if (sscanf(description, "BIVF%d", &ncentroids) == 1) {
|
|
369
|
+
IndexBinaryIVF *index_ivf = new IndexBinaryIVF(
|
|
370
|
+
new IndexBinaryFlat(d), d, ncentroids
|
|
371
|
+
);
|
|
372
|
+
index_ivf->own_fields = true;
|
|
373
|
+
index = index_ivf;
|
|
374
|
+
|
|
375
|
+
} else if (sscanf(description, "BHNSW%d", &M) == 1) {
|
|
376
|
+
IndexBinaryHNSW *index_hnsw = new IndexBinaryHNSW(d, M);
|
|
377
|
+
index = index_hnsw;
|
|
378
|
+
|
|
379
|
+
} else if (std::string(description) == "BFlat") {
|
|
380
|
+
index = new IndexBinaryFlat(d);
|
|
381
|
+
|
|
382
|
+
} else {
|
|
383
|
+
FAISS_THROW_IF_NOT_FMT(index, "description %s did not generate an index",
|
|
384
|
+
description);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return index;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
} // namespace faiss
|