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,550 @@
|
|
|
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
|
+
|
|
9
|
+
#include <faiss/IndexFlat.h>
|
|
10
|
+
#include <faiss/IndexIVFFlat.h>
|
|
11
|
+
#include <faiss/gpu/GpuIndexIVFFlat.h>
|
|
12
|
+
#include <faiss/gpu/StandardGpuResources.h>
|
|
13
|
+
#include <faiss/gpu/utils/DeviceUtils.h>
|
|
14
|
+
#include <faiss/gpu/test/TestUtils.h>
|
|
15
|
+
#include <cmath>
|
|
16
|
+
#include <gtest/gtest.h>
|
|
17
|
+
#include <sstream>
|
|
18
|
+
#include <vector>
|
|
19
|
+
|
|
20
|
+
// FIXME: figure out a better way to test fp16
|
|
21
|
+
constexpr float kF16MaxRelErr = 0.3f;
|
|
22
|
+
constexpr float kF32MaxRelErr = 0.03f;
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
struct Options {
|
|
26
|
+
Options() {
|
|
27
|
+
numAdd = 2 * faiss::gpu::randVal(2000, 5000);
|
|
28
|
+
dim = faiss::gpu::randVal(64, 200);
|
|
29
|
+
|
|
30
|
+
numCentroids = std::sqrt((float) numAdd / 2);
|
|
31
|
+
numTrain = numCentroids * 40;
|
|
32
|
+
nprobe = faiss::gpu::randVal(std::min(10, numCentroids), numCentroids);
|
|
33
|
+
numQuery = faiss::gpu::randVal(32, 100);
|
|
34
|
+
|
|
35
|
+
// Due to the approximate nature of the query and of floating point
|
|
36
|
+
// differences between GPU and CPU, to stay within our error bounds, only
|
|
37
|
+
// use a small k
|
|
38
|
+
k = std::min(faiss::gpu::randVal(10, 30), numAdd / 40);
|
|
39
|
+
indicesOpt = faiss::gpu::randSelect({
|
|
40
|
+
faiss::gpu::INDICES_CPU,
|
|
41
|
+
faiss::gpu::INDICES_32_BIT,
|
|
42
|
+
faiss::gpu::INDICES_64_BIT});
|
|
43
|
+
|
|
44
|
+
device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
std::string toString() const {
|
|
48
|
+
std::stringstream str;
|
|
49
|
+
str << "IVFFlat device " << device
|
|
50
|
+
<< " numVecs " << numAdd
|
|
51
|
+
<< " dim " << dim
|
|
52
|
+
<< " numCentroids " << numCentroids
|
|
53
|
+
<< " nprobe " << nprobe
|
|
54
|
+
<< " numQuery " << numQuery
|
|
55
|
+
<< " k " << k
|
|
56
|
+
<< " indicesOpt " << indicesOpt;
|
|
57
|
+
|
|
58
|
+
return str.str();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
int numAdd;
|
|
62
|
+
int dim;
|
|
63
|
+
int numCentroids;
|
|
64
|
+
int numTrain;
|
|
65
|
+
int nprobe;
|
|
66
|
+
int numQuery;
|
|
67
|
+
int k;
|
|
68
|
+
int device;
|
|
69
|
+
faiss::gpu::IndicesOptions indicesOpt;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
void queryTest(faiss::MetricType metricType,
|
|
73
|
+
bool useFloat16CoarseQuantizer,
|
|
74
|
+
int dimOverride = -1) {
|
|
75
|
+
for (int tries = 0; tries < 2; ++tries) {
|
|
76
|
+
Options opt;
|
|
77
|
+
opt.dim = dimOverride != -1 ? dimOverride : opt.dim;
|
|
78
|
+
|
|
79
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
80
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
81
|
+
|
|
82
|
+
faiss::IndexFlatL2 quantizerL2(opt.dim);
|
|
83
|
+
faiss::IndexFlatIP quantizerIP(opt.dim);
|
|
84
|
+
faiss::Index* quantizer =
|
|
85
|
+
metricType == faiss::METRIC_L2 ?
|
|
86
|
+
(faiss::Index*) &quantizerL2 : (faiss::Index*) &quantizerIP;
|
|
87
|
+
|
|
88
|
+
faiss::IndexIVFFlat cpuIndex(quantizer,
|
|
89
|
+
opt.dim, opt.numCentroids, metricType);
|
|
90
|
+
cpuIndex.train(opt.numTrain, trainVecs.data());
|
|
91
|
+
cpuIndex.add(opt.numAdd, addVecs.data());
|
|
92
|
+
cpuIndex.nprobe = opt.nprobe;
|
|
93
|
+
|
|
94
|
+
faiss::gpu::StandardGpuResources res;
|
|
95
|
+
res.noTempMemory();
|
|
96
|
+
|
|
97
|
+
faiss::gpu::GpuIndexIVFFlatConfig config;
|
|
98
|
+
config.device = opt.device;
|
|
99
|
+
config.indicesOptions = opt.indicesOpt;
|
|
100
|
+
config.flatConfig.useFloat16 = useFloat16CoarseQuantizer;
|
|
101
|
+
|
|
102
|
+
faiss::gpu::GpuIndexIVFFlat gpuIndex(&res,
|
|
103
|
+
cpuIndex.d,
|
|
104
|
+
cpuIndex.nlist,
|
|
105
|
+
cpuIndex.metric_type,
|
|
106
|
+
config);
|
|
107
|
+
gpuIndex.copyFrom(&cpuIndex);
|
|
108
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
109
|
+
|
|
110
|
+
bool compFloat16 = useFloat16CoarseQuantizer;
|
|
111
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
112
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
113
|
+
compFloat16 ? kF16MaxRelErr : kF32MaxRelErr,
|
|
114
|
+
// FIXME: the fp16 bounds are
|
|
115
|
+
// useless when math (the accumulator) is
|
|
116
|
+
// in fp16. Figure out another way to test
|
|
117
|
+
compFloat16 ? 0.70f : 0.1f,
|
|
118
|
+
compFloat16 ? 0.65f : 0.015f);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
void addTest(faiss::MetricType metricType,
|
|
123
|
+
bool useFloat16CoarseQuantizer) {
|
|
124
|
+
for (int tries = 0; tries < 2; ++tries) {
|
|
125
|
+
Options opt;
|
|
126
|
+
|
|
127
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
128
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
129
|
+
|
|
130
|
+
faiss::IndexFlatL2 quantizerL2(opt.dim);
|
|
131
|
+
faiss::IndexFlatIP quantizerIP(opt.dim);
|
|
132
|
+
faiss::Index* quantizer =
|
|
133
|
+
metricType == faiss::METRIC_L2 ?
|
|
134
|
+
(faiss::Index*) &quantizerL2 : (faiss::Index*) &quantizerIP;
|
|
135
|
+
|
|
136
|
+
faiss::IndexIVFFlat cpuIndex(quantizer,
|
|
137
|
+
opt.dim,
|
|
138
|
+
opt.numCentroids,
|
|
139
|
+
metricType);
|
|
140
|
+
cpuIndex.train(opt.numTrain, trainVecs.data());
|
|
141
|
+
cpuIndex.nprobe = opt.nprobe;
|
|
142
|
+
|
|
143
|
+
faiss::gpu::StandardGpuResources res;
|
|
144
|
+
res.noTempMemory();
|
|
145
|
+
|
|
146
|
+
faiss::gpu::GpuIndexIVFFlatConfig config;
|
|
147
|
+
config.device = opt.device;
|
|
148
|
+
config.indicesOptions = opt.indicesOpt;
|
|
149
|
+
config.flatConfig.useFloat16 = useFloat16CoarseQuantizer;
|
|
150
|
+
|
|
151
|
+
faiss::gpu::GpuIndexIVFFlat gpuIndex(&res,
|
|
152
|
+
cpuIndex.d,
|
|
153
|
+
cpuIndex.nlist,
|
|
154
|
+
cpuIndex.metric_type,
|
|
155
|
+
config);
|
|
156
|
+
gpuIndex.copyFrom(&cpuIndex);
|
|
157
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
158
|
+
|
|
159
|
+
cpuIndex.add(opt.numAdd, addVecs.data());
|
|
160
|
+
gpuIndex.add(opt.numAdd, addVecs.data());
|
|
161
|
+
|
|
162
|
+
bool compFloat16 = useFloat16CoarseQuantizer;
|
|
163
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
164
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
165
|
+
compFloat16 ? kF16MaxRelErr : kF32MaxRelErr,
|
|
166
|
+
compFloat16 ? 0.70f : 0.1f,
|
|
167
|
+
compFloat16 ? 0.30f : 0.015f);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
void copyToTest(bool useFloat16CoarseQuantizer) {
|
|
172
|
+
Options opt;
|
|
173
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
174
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
175
|
+
|
|
176
|
+
faiss::gpu::StandardGpuResources res;
|
|
177
|
+
res.noTempMemory();
|
|
178
|
+
|
|
179
|
+
faiss::gpu::GpuIndexIVFFlatConfig config;
|
|
180
|
+
config.device = opt.device;
|
|
181
|
+
config.indicesOptions = opt.indicesOpt;
|
|
182
|
+
config.flatConfig.useFloat16 = useFloat16CoarseQuantizer;
|
|
183
|
+
|
|
184
|
+
faiss::gpu::GpuIndexIVFFlat gpuIndex(&res,
|
|
185
|
+
opt.dim,
|
|
186
|
+
opt.numCentroids,
|
|
187
|
+
faiss::METRIC_L2,
|
|
188
|
+
config);
|
|
189
|
+
gpuIndex.train(opt.numTrain, trainVecs.data());
|
|
190
|
+
gpuIndex.add(opt.numAdd, addVecs.data());
|
|
191
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
192
|
+
|
|
193
|
+
// use garbage values to see if we overwrite then
|
|
194
|
+
faiss::IndexFlatL2 cpuQuantizer(1);
|
|
195
|
+
faiss::IndexIVFFlat cpuIndex(&cpuQuantizer, 1, 1, faiss::METRIC_L2);
|
|
196
|
+
cpuIndex.nprobe = 1;
|
|
197
|
+
|
|
198
|
+
gpuIndex.copyTo(&cpuIndex);
|
|
199
|
+
|
|
200
|
+
EXPECT_EQ(cpuIndex.ntotal, gpuIndex.ntotal);
|
|
201
|
+
EXPECT_EQ(gpuIndex.ntotal, opt.numAdd);
|
|
202
|
+
|
|
203
|
+
EXPECT_EQ(cpuIndex.d, gpuIndex.d);
|
|
204
|
+
EXPECT_EQ(cpuIndex.quantizer->d, gpuIndex.quantizer->d);
|
|
205
|
+
EXPECT_EQ(cpuIndex.d, opt.dim);
|
|
206
|
+
EXPECT_EQ(cpuIndex.nlist, gpuIndex.getNumLists());
|
|
207
|
+
EXPECT_EQ(cpuIndex.nprobe, gpuIndex.getNumProbes());
|
|
208
|
+
|
|
209
|
+
// Query both objects; results should be equivalent
|
|
210
|
+
bool compFloat16 = useFloat16CoarseQuantizer;
|
|
211
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
212
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
213
|
+
compFloat16 ? kF16MaxRelErr : kF32MaxRelErr,
|
|
214
|
+
compFloat16 ? 0.70f : 0.1f,
|
|
215
|
+
compFloat16 ? 0.30f : 0.015f);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
void copyFromTest(bool useFloat16CoarseQuantizer) {
|
|
219
|
+
Options opt;
|
|
220
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
221
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
222
|
+
|
|
223
|
+
faiss::IndexFlatL2 cpuQuantizer(opt.dim);
|
|
224
|
+
faiss::IndexIVFFlat cpuIndex(&cpuQuantizer,
|
|
225
|
+
opt.dim,
|
|
226
|
+
opt.numCentroids,
|
|
227
|
+
faiss::METRIC_L2);
|
|
228
|
+
cpuIndex.nprobe = opt.nprobe;
|
|
229
|
+
cpuIndex.train(opt.numTrain, trainVecs.data());
|
|
230
|
+
cpuIndex.add(opt.numAdd, addVecs.data());
|
|
231
|
+
|
|
232
|
+
// use garbage values to see if we overwrite then
|
|
233
|
+
faiss::gpu::StandardGpuResources res;
|
|
234
|
+
res.noTempMemory();
|
|
235
|
+
|
|
236
|
+
faiss::gpu::GpuIndexIVFFlatConfig config;
|
|
237
|
+
config.device = opt.device;
|
|
238
|
+
config.indicesOptions = opt.indicesOpt;
|
|
239
|
+
config.flatConfig.useFloat16 = useFloat16CoarseQuantizer;
|
|
240
|
+
|
|
241
|
+
faiss::gpu::GpuIndexIVFFlat gpuIndex(&res,
|
|
242
|
+
1,
|
|
243
|
+
1,
|
|
244
|
+
faiss::METRIC_L2,
|
|
245
|
+
config);
|
|
246
|
+
gpuIndex.setNumProbes(1);
|
|
247
|
+
|
|
248
|
+
gpuIndex.copyFrom(&cpuIndex);
|
|
249
|
+
|
|
250
|
+
EXPECT_EQ(cpuIndex.ntotal, gpuIndex.ntotal);
|
|
251
|
+
EXPECT_EQ(gpuIndex.ntotal, opt.numAdd);
|
|
252
|
+
|
|
253
|
+
EXPECT_EQ(cpuIndex.d, gpuIndex.d);
|
|
254
|
+
EXPECT_EQ(cpuIndex.d, opt.dim);
|
|
255
|
+
EXPECT_EQ(cpuIndex.nlist, gpuIndex.getNumLists());
|
|
256
|
+
EXPECT_EQ(cpuIndex.nprobe, gpuIndex.getNumProbes());
|
|
257
|
+
|
|
258
|
+
// Query both objects; results should be equivalent
|
|
259
|
+
bool compFloat16 = useFloat16CoarseQuantizer;
|
|
260
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
261
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
262
|
+
compFloat16 ? kF16MaxRelErr : kF32MaxRelErr,
|
|
263
|
+
compFloat16 ? 0.70f : 0.1f,
|
|
264
|
+
compFloat16 ? 0.30f : 0.015f);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
TEST(TestGpuIndexIVFFlat, Float32_32_Add_L2) {
|
|
268
|
+
addTest(faiss::METRIC_L2, false);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
TEST(TestGpuIndexIVFFlat, Float32_32_Add_IP) {
|
|
272
|
+
addTest(faiss::METRIC_INNER_PRODUCT, false);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
TEST(TestGpuIndexIVFFlat, Float16_32_Add_L2) {
|
|
276
|
+
addTest(faiss::METRIC_L2, true);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
TEST(TestGpuIndexIVFFlat, Float16_32_Add_IP) {
|
|
280
|
+
addTest(faiss::METRIC_INNER_PRODUCT, true);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
//
|
|
284
|
+
// General query tests
|
|
285
|
+
//
|
|
286
|
+
|
|
287
|
+
TEST(TestGpuIndexIVFFlat, Float32_Query_L2) {
|
|
288
|
+
queryTest(faiss::METRIC_L2, false);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
TEST(TestGpuIndexIVFFlat, Float32_Query_IP) {
|
|
292
|
+
queryTest(faiss::METRIC_INNER_PRODUCT, false);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// float16 coarse quantizer
|
|
296
|
+
|
|
297
|
+
TEST(TestGpuIndexIVFFlat, Float16_32_Query_L2) {
|
|
298
|
+
queryTest(faiss::METRIC_L2, true);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
TEST(TestGpuIndexIVFFlat, Float16_32_Query_IP) {
|
|
302
|
+
queryTest(faiss::METRIC_INNER_PRODUCT, true);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
//
|
|
306
|
+
// There are IVF list scanning specializations for 64-d and 128-d that we
|
|
307
|
+
// make sure we explicitly test here
|
|
308
|
+
//
|
|
309
|
+
|
|
310
|
+
TEST(TestGpuIndexIVFFlat, Float32_Query_L2_64) {
|
|
311
|
+
queryTest(faiss::METRIC_L2, false, 64);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
TEST(TestGpuIndexIVFFlat, Float32_Query_IP_64) {
|
|
315
|
+
queryTest(faiss::METRIC_INNER_PRODUCT, false, 64);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
TEST(TestGpuIndexIVFFlat, Float32_Query_L2_128) {
|
|
319
|
+
queryTest(faiss::METRIC_L2, false, 128);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
TEST(TestGpuIndexIVFFlat, Float32_Query_IP_128) {
|
|
323
|
+
queryTest(faiss::METRIC_INNER_PRODUCT, false, 128);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
//
|
|
327
|
+
// Copy tests
|
|
328
|
+
//
|
|
329
|
+
|
|
330
|
+
TEST(TestGpuIndexIVFFlat, Float32_32_CopyTo) {
|
|
331
|
+
copyToTest(false);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
TEST(TestGpuIndexIVFFlat, Float32_32_CopyFrom) {
|
|
335
|
+
copyFromTest(false);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
TEST(TestGpuIndexIVFFlat, Float32_negative) {
|
|
339
|
+
Options opt;
|
|
340
|
+
|
|
341
|
+
auto trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
342
|
+
auto addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
343
|
+
|
|
344
|
+
// Put all vecs on negative side
|
|
345
|
+
for (auto& f : trainVecs) {
|
|
346
|
+
f = std::abs(f) * -1.0f;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
for (auto& f : addVecs) {
|
|
350
|
+
f *= std::abs(f) * -1.0f;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
faiss::IndexFlatIP quantizerIP(opt.dim);
|
|
354
|
+
faiss::Index* quantizer = (faiss::Index*) &quantizerIP;
|
|
355
|
+
|
|
356
|
+
faiss::IndexIVFFlat cpuIndex(quantizer,
|
|
357
|
+
opt.dim, opt.numCentroids,
|
|
358
|
+
faiss::METRIC_INNER_PRODUCT);
|
|
359
|
+
cpuIndex.train(opt.numTrain, trainVecs.data());
|
|
360
|
+
cpuIndex.add(opt.numAdd, addVecs.data());
|
|
361
|
+
cpuIndex.nprobe = opt.nprobe;
|
|
362
|
+
|
|
363
|
+
faiss::gpu::StandardGpuResources res;
|
|
364
|
+
res.noTempMemory();
|
|
365
|
+
|
|
366
|
+
faiss::gpu::GpuIndexIVFFlatConfig config;
|
|
367
|
+
config.device = opt.device;
|
|
368
|
+
config.indicesOptions = opt.indicesOpt;
|
|
369
|
+
|
|
370
|
+
faiss::gpu::GpuIndexIVFFlat gpuIndex(&res,
|
|
371
|
+
cpuIndex.d,
|
|
372
|
+
cpuIndex.nlist,
|
|
373
|
+
cpuIndex.metric_type,
|
|
374
|
+
config);
|
|
375
|
+
gpuIndex.copyFrom(&cpuIndex);
|
|
376
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
377
|
+
|
|
378
|
+
// Construct a positive test set
|
|
379
|
+
auto queryVecs = faiss::gpu::randVecs(opt.numQuery, opt.dim);
|
|
380
|
+
|
|
381
|
+
// Put all vecs on positive size
|
|
382
|
+
for (auto& f : queryVecs) {
|
|
383
|
+
f = std::abs(f);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
bool compFloat16 = false;
|
|
387
|
+
faiss::gpu::compareIndices(queryVecs,
|
|
388
|
+
cpuIndex, gpuIndex,
|
|
389
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
390
|
+
compFloat16 ? kF16MaxRelErr : kF32MaxRelErr,
|
|
391
|
+
// FIXME: the fp16 bounds are
|
|
392
|
+
// useless when math (the accumulator) is
|
|
393
|
+
// in fp16. Figure out another way to test
|
|
394
|
+
compFloat16 ? 0.99f : 0.1f,
|
|
395
|
+
compFloat16 ? 0.65f : 0.015f);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
//
|
|
399
|
+
// NaN tests
|
|
400
|
+
//
|
|
401
|
+
|
|
402
|
+
TEST(TestGpuIndexIVFFlat, QueryNaN) {
|
|
403
|
+
Options opt;
|
|
404
|
+
|
|
405
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
406
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
407
|
+
|
|
408
|
+
faiss::gpu::StandardGpuResources res;
|
|
409
|
+
res.noTempMemory();
|
|
410
|
+
|
|
411
|
+
faiss::gpu::GpuIndexIVFFlatConfig config;
|
|
412
|
+
config.device = opt.device;
|
|
413
|
+
config.indicesOptions = opt.indicesOpt;
|
|
414
|
+
config.flatConfig.useFloat16 = faiss::gpu::randBool();
|
|
415
|
+
|
|
416
|
+
faiss::gpu::GpuIndexIVFFlat gpuIndex(&res,
|
|
417
|
+
opt.dim,
|
|
418
|
+
opt.numCentroids,
|
|
419
|
+
faiss::METRIC_L2,
|
|
420
|
+
config);
|
|
421
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
422
|
+
|
|
423
|
+
gpuIndex.train(opt.numTrain, trainVecs.data());
|
|
424
|
+
gpuIndex.add(opt.numAdd, addVecs.data());
|
|
425
|
+
|
|
426
|
+
int numQuery = 10;
|
|
427
|
+
std::vector<float> nans(numQuery * opt.dim,
|
|
428
|
+
std::numeric_limits<float>::quiet_NaN());
|
|
429
|
+
|
|
430
|
+
std::vector<float> distances(numQuery * opt.k, 0);
|
|
431
|
+
std::vector<faiss::Index::idx_t> indices(numQuery * opt.k, 0);
|
|
432
|
+
|
|
433
|
+
gpuIndex.search(numQuery,
|
|
434
|
+
nans.data(),
|
|
435
|
+
opt.k,
|
|
436
|
+
distances.data(),
|
|
437
|
+
indices.data());
|
|
438
|
+
|
|
439
|
+
for (int q = 0; q < numQuery; ++q) {
|
|
440
|
+
for (int k = 0; k < opt.k; ++k) {
|
|
441
|
+
EXPECT_EQ(indices[q * opt.k + k], -1);
|
|
442
|
+
EXPECT_EQ(distances[q * opt.k + k], std::numeric_limits<float>::max());
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
TEST(TestGpuIndexIVFFlat, AddNaN) {
|
|
448
|
+
Options opt;
|
|
449
|
+
|
|
450
|
+
faiss::gpu::StandardGpuResources res;
|
|
451
|
+
res.noTempMemory();
|
|
452
|
+
|
|
453
|
+
faiss::gpu::GpuIndexIVFFlatConfig config;
|
|
454
|
+
config.device = opt.device;
|
|
455
|
+
config.indicesOptions = opt.indicesOpt;
|
|
456
|
+
config.flatConfig.useFloat16 = faiss::gpu::randBool();
|
|
457
|
+
|
|
458
|
+
faiss::gpu::GpuIndexIVFFlat gpuIndex(&res,
|
|
459
|
+
opt.dim,
|
|
460
|
+
opt.numCentroids,
|
|
461
|
+
faiss::METRIC_L2,
|
|
462
|
+
config);
|
|
463
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
464
|
+
|
|
465
|
+
int numNans = 10;
|
|
466
|
+
std::vector<float> nans(numNans * opt.dim,
|
|
467
|
+
std::numeric_limits<float>::quiet_NaN());
|
|
468
|
+
|
|
469
|
+
// Make one vector valid, which should actually add
|
|
470
|
+
for (int i = 0; i < opt.dim; ++i) {
|
|
471
|
+
nans[i] = 0.0f;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
475
|
+
gpuIndex.train(opt.numTrain, trainVecs.data());
|
|
476
|
+
|
|
477
|
+
// should not crash
|
|
478
|
+
EXPECT_EQ(gpuIndex.ntotal, 0);
|
|
479
|
+
gpuIndex.add(numNans, nans.data());
|
|
480
|
+
|
|
481
|
+
std::vector<float> queryVecs = faiss::gpu::randVecs(opt.numQuery, opt.dim);
|
|
482
|
+
std::vector<float> distance(opt.numQuery * opt.k, 0);
|
|
483
|
+
std::vector<faiss::Index::idx_t> indices(opt.numQuery * opt.k, 0);
|
|
484
|
+
|
|
485
|
+
// should not crash
|
|
486
|
+
gpuIndex.search(opt.numQuery, queryVecs.data(), opt.k,
|
|
487
|
+
distance.data(), indices.data());
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
TEST(TestGpuIndexIVFFlat, UnifiedMemory) {
|
|
491
|
+
// Construct on a random device to test multi-device, if we have
|
|
492
|
+
// multiple devices
|
|
493
|
+
int device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
|
|
494
|
+
|
|
495
|
+
if (!faiss::gpu::getFullUnifiedMemSupport(device)) {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
int dim = 128;
|
|
500
|
+
|
|
501
|
+
int numCentroids = 256;
|
|
502
|
+
// Unfortunately it would take forever to add 24 GB in IVFPQ data,
|
|
503
|
+
// so just perform a small test with data allocated in the unified
|
|
504
|
+
// memory address space
|
|
505
|
+
size_t numAdd = 10000;
|
|
506
|
+
size_t numTrain = numCentroids * 40;
|
|
507
|
+
int numQuery = 10;
|
|
508
|
+
int k = 10;
|
|
509
|
+
int nprobe = 8;
|
|
510
|
+
|
|
511
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(numTrain, dim);
|
|
512
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(numAdd, dim);
|
|
513
|
+
|
|
514
|
+
faiss::IndexFlatL2 quantizer(dim);
|
|
515
|
+
faiss::IndexIVFFlat cpuIndex(&quantizer, dim, numCentroids, faiss::METRIC_L2);
|
|
516
|
+
|
|
517
|
+
cpuIndex.train(numTrain, trainVecs.data());
|
|
518
|
+
cpuIndex.add(numAdd, addVecs.data());
|
|
519
|
+
cpuIndex.nprobe = nprobe;
|
|
520
|
+
|
|
521
|
+
faiss::gpu::StandardGpuResources res;
|
|
522
|
+
res.noTempMemory();
|
|
523
|
+
|
|
524
|
+
faiss::gpu::GpuIndexIVFFlatConfig config;
|
|
525
|
+
config.device = device;
|
|
526
|
+
config.memorySpace = faiss::gpu::MemorySpace::Unified;
|
|
527
|
+
|
|
528
|
+
faiss::gpu::GpuIndexIVFFlat gpuIndex(&res,
|
|
529
|
+
dim,
|
|
530
|
+
numCentroids,
|
|
531
|
+
faiss::METRIC_L2,
|
|
532
|
+
config);
|
|
533
|
+
gpuIndex.copyFrom(&cpuIndex);
|
|
534
|
+
gpuIndex.setNumProbes(nprobe);
|
|
535
|
+
|
|
536
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
537
|
+
numQuery, dim, k, "Unified Memory",
|
|
538
|
+
kF32MaxRelErr,
|
|
539
|
+
0.1f,
|
|
540
|
+
0.015f);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
int main(int argc, char** argv) {
|
|
544
|
+
testing::InitGoogleTest(&argc, argv);
|
|
545
|
+
|
|
546
|
+
// just run with a fixed test seed
|
|
547
|
+
faiss::gpu::setTestSeed(100);
|
|
548
|
+
|
|
549
|
+
return RUN_ALL_TESTS();
|
|
550
|
+
}
|