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,450 @@
|
|
|
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/IndexIVFPQ.h>
|
|
11
|
+
#include <faiss/gpu/GpuIndexIVFPQ.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
|
+
|
|
21
|
+
void pickEncoding(int& codes, int& dim) {
|
|
22
|
+
std::vector<int> codeSizes{
|
|
23
|
+
3, 4, 8, 12, 16, 20, 24,
|
|
24
|
+
28, 32, 40, 48, 56, 64, 96
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Above 32 doesn't work with no precomputed codes
|
|
28
|
+
std::vector<int> dimSizes{4, 8, 10, 12, 16, 20, 24, 28, 32};
|
|
29
|
+
|
|
30
|
+
while (true) {
|
|
31
|
+
codes = codeSizes[faiss::gpu::randVal(0, codeSizes.size() - 1)];
|
|
32
|
+
dim = codes * dimSizes[faiss::gpu::randVal(0, dimSizes.size() - 1)];
|
|
33
|
+
|
|
34
|
+
// for such a small test, super-low or high dim is more likely to
|
|
35
|
+
// generate comparison errors
|
|
36
|
+
if (dim < 256 && dim >= 64) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
struct Options {
|
|
43
|
+
Options() {
|
|
44
|
+
numAdd = faiss::gpu::randVal(2000, 5000);
|
|
45
|
+
numCentroids = std::sqrt((float) numAdd);
|
|
46
|
+
numTrain = numCentroids * 40;
|
|
47
|
+
|
|
48
|
+
pickEncoding(codes, dim);
|
|
49
|
+
|
|
50
|
+
// TODO: Change back to `faiss::gpu::randVal(3, 7)` when we officially
|
|
51
|
+
// support non-multiple of 8 subcodes for IVFPQ.
|
|
52
|
+
bitsPerCode = 8;
|
|
53
|
+
nprobe = std::min(faiss::gpu::randVal(40, 1000), numCentroids);
|
|
54
|
+
numQuery = faiss::gpu::randVal(1, 8);
|
|
55
|
+
|
|
56
|
+
// Due to the approximate nature of the query and of floating point
|
|
57
|
+
// differences between GPU and CPU, to stay within our error bounds, only
|
|
58
|
+
// use a small k
|
|
59
|
+
k = std::min(faiss::gpu::randVal(5, 20), numAdd / 40);
|
|
60
|
+
usePrecomputed = faiss::gpu::randBool();
|
|
61
|
+
indicesOpt = faiss::gpu::randSelect({
|
|
62
|
+
faiss::gpu::INDICES_CPU,
|
|
63
|
+
faiss::gpu::INDICES_32_BIT,
|
|
64
|
+
faiss::gpu::INDICES_64_BIT});
|
|
65
|
+
if (codes > 48) {
|
|
66
|
+
// large codes can only fit using float16
|
|
67
|
+
useFloat16 = true;
|
|
68
|
+
} else {
|
|
69
|
+
useFloat16 = faiss::gpu::randBool();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
std::string toString() const {
|
|
76
|
+
std::stringstream str;
|
|
77
|
+
str << "IVFPQ device " << device
|
|
78
|
+
<< " numVecs " << numAdd
|
|
79
|
+
<< " dim " << dim
|
|
80
|
+
<< " numCentroids " << numCentroids
|
|
81
|
+
<< " codes " << codes
|
|
82
|
+
<< " bitsPerCode " << bitsPerCode
|
|
83
|
+
<< " nprobe " << nprobe
|
|
84
|
+
<< " numQuery " << numQuery
|
|
85
|
+
<< " k " << k
|
|
86
|
+
<< " usePrecomputed " << usePrecomputed
|
|
87
|
+
<< " indicesOpt " << indicesOpt
|
|
88
|
+
<< " useFloat16 " << useFloat16;
|
|
89
|
+
|
|
90
|
+
return str.str();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
float getCompareEpsilon() const {
|
|
94
|
+
return 0.03f;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
float getPctMaxDiff1() const {
|
|
98
|
+
return useFloat16 ? 0.30f : 0.10f;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
float getPctMaxDiffN() const {
|
|
102
|
+
return useFloat16 ? 0.05f : 0.02f;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
int numAdd;
|
|
106
|
+
int numCentroids;
|
|
107
|
+
int numTrain;
|
|
108
|
+
int codes;
|
|
109
|
+
int dim;
|
|
110
|
+
int bitsPerCode;
|
|
111
|
+
int nprobe;
|
|
112
|
+
int numQuery;
|
|
113
|
+
int k;
|
|
114
|
+
bool usePrecomputed;
|
|
115
|
+
faiss::gpu::IndicesOptions indicesOpt;
|
|
116
|
+
bool useFloat16;
|
|
117
|
+
int device;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
TEST(TestGpuIndexIVFPQ, Query) {
|
|
121
|
+
for (int tries = 0; tries < 2; ++tries) {
|
|
122
|
+
Options opt;
|
|
123
|
+
|
|
124
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
125
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
126
|
+
|
|
127
|
+
faiss::IndexFlatL2 coarseQuantizer(opt.dim);
|
|
128
|
+
faiss::IndexIVFPQ cpuIndex(&coarseQuantizer, opt.dim, opt.numCentroids,
|
|
129
|
+
opt.codes, opt.bitsPerCode);
|
|
130
|
+
cpuIndex.nprobe = opt.nprobe;
|
|
131
|
+
cpuIndex.train(opt.numTrain, trainVecs.data());
|
|
132
|
+
cpuIndex.add(opt.numAdd, addVecs.data());
|
|
133
|
+
|
|
134
|
+
faiss::gpu::StandardGpuResources res;
|
|
135
|
+
res.noTempMemory();
|
|
136
|
+
|
|
137
|
+
faiss::gpu::GpuIndexIVFPQConfig config;
|
|
138
|
+
config.device = opt.device;
|
|
139
|
+
config.usePrecomputedTables = opt.usePrecomputed;
|
|
140
|
+
config.indicesOptions = opt.indicesOpt;
|
|
141
|
+
config.useFloat16LookupTables = opt.useFloat16;
|
|
142
|
+
|
|
143
|
+
faiss::gpu::GpuIndexIVFPQ gpuIndex(&res, &cpuIndex, config);
|
|
144
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
145
|
+
|
|
146
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
147
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
148
|
+
opt.getCompareEpsilon(),
|
|
149
|
+
opt.getPctMaxDiff1(),
|
|
150
|
+
opt.getPctMaxDiffN());
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
TEST(TestGpuIndexIVFPQ, Add) {
|
|
155
|
+
for (int tries = 0; tries < 2; ++tries) {
|
|
156
|
+
Options opt;
|
|
157
|
+
|
|
158
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
159
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
160
|
+
|
|
161
|
+
faiss::IndexFlatL2 coarseQuantizer(opt.dim);
|
|
162
|
+
faiss::IndexIVFPQ cpuIndex(&coarseQuantizer, opt.dim, opt.numCentroids,
|
|
163
|
+
opt.codes, opt.bitsPerCode);
|
|
164
|
+
cpuIndex.nprobe = opt.nprobe;
|
|
165
|
+
cpuIndex.train(opt.numTrain, trainVecs.data());
|
|
166
|
+
|
|
167
|
+
faiss::gpu::StandardGpuResources res;
|
|
168
|
+
res.noTempMemory();
|
|
169
|
+
|
|
170
|
+
faiss::gpu::GpuIndexIVFPQConfig config;
|
|
171
|
+
config.device = opt.device;
|
|
172
|
+
config.usePrecomputedTables = opt.usePrecomputed;
|
|
173
|
+
config.indicesOptions = opt.indicesOpt;
|
|
174
|
+
config.useFloat16LookupTables = opt.useFloat16;
|
|
175
|
+
|
|
176
|
+
faiss::gpu::GpuIndexIVFPQ gpuIndex(&res, &cpuIndex, config);
|
|
177
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
178
|
+
|
|
179
|
+
gpuIndex.add(opt.numAdd, addVecs.data());
|
|
180
|
+
cpuIndex.add(opt.numAdd, addVecs.data());
|
|
181
|
+
|
|
182
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
183
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
184
|
+
opt.getCompareEpsilon(),
|
|
185
|
+
opt.getPctMaxDiff1(),
|
|
186
|
+
opt.getPctMaxDiffN());
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
TEST(TestGpuIndexIVFPQ, CopyTo) {
|
|
191
|
+
Options opt;
|
|
192
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
193
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
194
|
+
|
|
195
|
+
faiss::gpu::StandardGpuResources res;
|
|
196
|
+
res.noTempMemory();
|
|
197
|
+
|
|
198
|
+
faiss::gpu::GpuIndexIVFPQConfig config;
|
|
199
|
+
config.device = opt.device;
|
|
200
|
+
config.usePrecomputedTables = opt.usePrecomputed;
|
|
201
|
+
config.indicesOptions = opt.indicesOpt;
|
|
202
|
+
config.useFloat16LookupTables = opt.useFloat16;
|
|
203
|
+
|
|
204
|
+
faiss::gpu::GpuIndexIVFPQ gpuIndex(&res,
|
|
205
|
+
opt.dim,
|
|
206
|
+
opt.numCentroids,
|
|
207
|
+
opt.codes,
|
|
208
|
+
opt.bitsPerCode,
|
|
209
|
+
faiss::METRIC_L2,
|
|
210
|
+
config);
|
|
211
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
212
|
+
gpuIndex.train(opt.numTrain, trainVecs.data());
|
|
213
|
+
gpuIndex.add(opt.numAdd, addVecs.data());
|
|
214
|
+
|
|
215
|
+
// Use garbage values to see if we overwrite them
|
|
216
|
+
faiss::IndexFlatL2 cpuQuantizer(1);
|
|
217
|
+
faiss::IndexIVFPQ cpuIndex(&cpuQuantizer, 1, 1, 1, 1);
|
|
218
|
+
|
|
219
|
+
gpuIndex.copyTo(&cpuIndex);
|
|
220
|
+
|
|
221
|
+
EXPECT_EQ(cpuIndex.ntotal, gpuIndex.ntotal);
|
|
222
|
+
EXPECT_EQ(gpuIndex.ntotal, opt.numAdd);
|
|
223
|
+
|
|
224
|
+
EXPECT_EQ(cpuIndex.d, gpuIndex.d);
|
|
225
|
+
EXPECT_EQ(cpuIndex.d, opt.dim);
|
|
226
|
+
EXPECT_EQ(cpuIndex.nlist, gpuIndex.getNumLists());
|
|
227
|
+
EXPECT_EQ(cpuIndex.nprobe, gpuIndex.getNumProbes());
|
|
228
|
+
EXPECT_EQ(cpuIndex.pq.M, gpuIndex.getNumSubQuantizers());
|
|
229
|
+
EXPECT_EQ(gpuIndex.getNumSubQuantizers(), opt.codes);
|
|
230
|
+
EXPECT_EQ(cpuIndex.pq.nbits, gpuIndex.getBitsPerCode());
|
|
231
|
+
EXPECT_EQ(gpuIndex.getBitsPerCode(), opt.bitsPerCode);
|
|
232
|
+
|
|
233
|
+
// Query both objects; results should be equivalent
|
|
234
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
235
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
236
|
+
opt.getCompareEpsilon(),
|
|
237
|
+
opt.getPctMaxDiff1(),
|
|
238
|
+
opt.getPctMaxDiffN());
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
TEST(TestGpuIndexIVFPQ, CopyFrom) {
|
|
242
|
+
Options opt;
|
|
243
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
244
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
245
|
+
|
|
246
|
+
faiss::IndexFlatL2 coarseQuantizer(opt.dim);
|
|
247
|
+
faiss::IndexIVFPQ cpuIndex(&coarseQuantizer, opt.dim, opt.numCentroids,
|
|
248
|
+
opt.codes, opt.bitsPerCode);
|
|
249
|
+
cpuIndex.nprobe = opt.nprobe;
|
|
250
|
+
cpuIndex.train(opt.numTrain, trainVecs.data());
|
|
251
|
+
cpuIndex.add(opt.numAdd, addVecs.data());
|
|
252
|
+
|
|
253
|
+
// Use garbage values to see if we overwrite them
|
|
254
|
+
faiss::gpu::StandardGpuResources res;
|
|
255
|
+
res.noTempMemory();
|
|
256
|
+
|
|
257
|
+
faiss::gpu::GpuIndexIVFPQConfig config;
|
|
258
|
+
config.device = opt.device;
|
|
259
|
+
config.usePrecomputedTables = opt.usePrecomputed;
|
|
260
|
+
config.indicesOptions = opt.indicesOpt;
|
|
261
|
+
config.useFloat16LookupTables = opt.useFloat16;
|
|
262
|
+
|
|
263
|
+
faiss::gpu::GpuIndexIVFPQ
|
|
264
|
+
gpuIndex(&res, 1, 1, 1, 1, faiss::METRIC_L2, config);
|
|
265
|
+
gpuIndex.setNumProbes(1);
|
|
266
|
+
|
|
267
|
+
gpuIndex.copyFrom(&cpuIndex);
|
|
268
|
+
|
|
269
|
+
// Make sure we are equivalent
|
|
270
|
+
EXPECT_EQ(cpuIndex.ntotal, gpuIndex.ntotal);
|
|
271
|
+
EXPECT_EQ(gpuIndex.ntotal, opt.numAdd);
|
|
272
|
+
|
|
273
|
+
EXPECT_EQ(cpuIndex.d, gpuIndex.d);
|
|
274
|
+
EXPECT_EQ(cpuIndex.d, opt.dim);
|
|
275
|
+
EXPECT_EQ(cpuIndex.nlist, gpuIndex.getNumLists());
|
|
276
|
+
EXPECT_EQ(cpuIndex.nprobe, gpuIndex.getNumProbes());
|
|
277
|
+
EXPECT_EQ(cpuIndex.pq.M, gpuIndex.getNumSubQuantizers());
|
|
278
|
+
EXPECT_EQ(gpuIndex.getNumSubQuantizers(), opt.codes);
|
|
279
|
+
EXPECT_EQ(cpuIndex.pq.nbits, gpuIndex.getBitsPerCode());
|
|
280
|
+
EXPECT_EQ(gpuIndex.getBitsPerCode(), opt.bitsPerCode);
|
|
281
|
+
|
|
282
|
+
// Query both objects; results should be equivalent
|
|
283
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
284
|
+
opt.numQuery, opt.dim, opt.k, opt.toString(),
|
|
285
|
+
opt.getCompareEpsilon(),
|
|
286
|
+
opt.getPctMaxDiff1(),
|
|
287
|
+
opt.getPctMaxDiffN());
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
TEST(TestGpuIndexIVFPQ, QueryNaN) {
|
|
291
|
+
Options opt;
|
|
292
|
+
|
|
293
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
294
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(opt.numAdd, opt.dim);
|
|
295
|
+
|
|
296
|
+
faiss::gpu::StandardGpuResources res;
|
|
297
|
+
res.noTempMemory();
|
|
298
|
+
|
|
299
|
+
faiss::gpu::GpuIndexIVFPQConfig config;
|
|
300
|
+
config.device = opt.device;
|
|
301
|
+
config.usePrecomputedTables = opt.usePrecomputed;
|
|
302
|
+
config.indicesOptions = opt.indicesOpt;
|
|
303
|
+
config.useFloat16LookupTables = opt.useFloat16;
|
|
304
|
+
|
|
305
|
+
faiss::gpu::GpuIndexIVFPQ gpuIndex(&res,
|
|
306
|
+
opt.dim,
|
|
307
|
+
opt.numCentroids,
|
|
308
|
+
opt.codes,
|
|
309
|
+
opt.bitsPerCode,
|
|
310
|
+
faiss::METRIC_L2,
|
|
311
|
+
config);
|
|
312
|
+
|
|
313
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
314
|
+
|
|
315
|
+
gpuIndex.train(opt.numTrain, trainVecs.data());
|
|
316
|
+
gpuIndex.add(opt.numAdd, addVecs.data());
|
|
317
|
+
|
|
318
|
+
int numQuery = 5;
|
|
319
|
+
std::vector<float> nans(numQuery * opt.dim,
|
|
320
|
+
std::numeric_limits<float>::quiet_NaN());
|
|
321
|
+
|
|
322
|
+
std::vector<float> distances(numQuery * opt.k, 0);
|
|
323
|
+
std::vector<faiss::Index::idx_t> indices(numQuery * opt.k, 0);
|
|
324
|
+
|
|
325
|
+
gpuIndex.search(numQuery,
|
|
326
|
+
nans.data(),
|
|
327
|
+
opt.k,
|
|
328
|
+
distances.data(),
|
|
329
|
+
indices.data());
|
|
330
|
+
|
|
331
|
+
for (int q = 0; q < numQuery; ++q) {
|
|
332
|
+
for (int k = 0; k < opt.k; ++k) {
|
|
333
|
+
EXPECT_EQ(indices[q * opt.k + k], -1);
|
|
334
|
+
EXPECT_EQ(distances[q * opt.k + k], std::numeric_limits<float>::max());
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
TEST(TestGpuIndexIVFPQ, AddNaN) {
|
|
340
|
+
Options opt;
|
|
341
|
+
|
|
342
|
+
faiss::gpu::StandardGpuResources res;
|
|
343
|
+
res.noTempMemory();
|
|
344
|
+
|
|
345
|
+
faiss::gpu::GpuIndexIVFPQConfig config;
|
|
346
|
+
config.device = opt.device;
|
|
347
|
+
config.usePrecomputedTables = opt.usePrecomputed;
|
|
348
|
+
config.indicesOptions = opt.indicesOpt;
|
|
349
|
+
config.useFloat16LookupTables = opt.useFloat16;
|
|
350
|
+
|
|
351
|
+
faiss::gpu::GpuIndexIVFPQ gpuIndex(&res,
|
|
352
|
+
opt.dim,
|
|
353
|
+
opt.numCentroids,
|
|
354
|
+
opt.codes,
|
|
355
|
+
opt.bitsPerCode,
|
|
356
|
+
faiss::METRIC_L2,
|
|
357
|
+
config);
|
|
358
|
+
|
|
359
|
+
gpuIndex.setNumProbes(opt.nprobe);
|
|
360
|
+
|
|
361
|
+
int numNans = 10;
|
|
362
|
+
std::vector<float> nans(numNans * opt.dim,
|
|
363
|
+
std::numeric_limits<float>::quiet_NaN());
|
|
364
|
+
|
|
365
|
+
// Make one vector valid, which should actually add
|
|
366
|
+
for (int i = 0; i < opt.dim; ++i) {
|
|
367
|
+
nans[i] = 0.0f;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(opt.numTrain, opt.dim);
|
|
371
|
+
gpuIndex.train(opt.numTrain, trainVecs.data());
|
|
372
|
+
|
|
373
|
+
// should not crash
|
|
374
|
+
EXPECT_EQ(gpuIndex.ntotal, 0);
|
|
375
|
+
gpuIndex.add(numNans, nans.data());
|
|
376
|
+
|
|
377
|
+
std::vector<float> queryVecs = faiss::gpu::randVecs(opt.numQuery, opt.dim);
|
|
378
|
+
std::vector<float> distance(opt.numQuery * opt.k, 0);
|
|
379
|
+
std::vector<faiss::Index::idx_t> indices(opt.numQuery * opt.k, 0);
|
|
380
|
+
|
|
381
|
+
// should not crash
|
|
382
|
+
gpuIndex.search(opt.numQuery, queryVecs.data(), opt.k,
|
|
383
|
+
distance.data(), indices.data());
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
TEST(TestGpuIndexIVFPQ, UnifiedMemory) {
|
|
387
|
+
// Construct on a random device to test multi-device, if we have
|
|
388
|
+
// multiple devices
|
|
389
|
+
int device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
|
|
390
|
+
|
|
391
|
+
if (!faiss::gpu::getFullUnifiedMemSupport(device)) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
int dim = 128;
|
|
396
|
+
|
|
397
|
+
int numCentroids = 256;
|
|
398
|
+
// Unfortunately it would take forever to add 24 GB in IVFPQ data,
|
|
399
|
+
// so just perform a small test with data allocated in the unified
|
|
400
|
+
// memory address space
|
|
401
|
+
size_t numAdd = 10000;
|
|
402
|
+
size_t numTrain = numCentroids * 40;
|
|
403
|
+
int numQuery = 10;
|
|
404
|
+
int k = 10;
|
|
405
|
+
int nprobe = 8;
|
|
406
|
+
int codes = 8;
|
|
407
|
+
int bitsPerCode = 8;
|
|
408
|
+
|
|
409
|
+
std::vector<float> trainVecs = faiss::gpu::randVecs(numTrain, dim);
|
|
410
|
+
std::vector<float> addVecs = faiss::gpu::randVecs(numAdd, dim);
|
|
411
|
+
|
|
412
|
+
faiss::IndexFlatL2 quantizer(dim);
|
|
413
|
+
faiss::IndexIVFPQ cpuIndex(&quantizer, dim, numCentroids, codes, bitsPerCode);
|
|
414
|
+
|
|
415
|
+
cpuIndex.train(numTrain, trainVecs.data());
|
|
416
|
+
cpuIndex.add(numAdd, addVecs.data());
|
|
417
|
+
cpuIndex.nprobe = nprobe;
|
|
418
|
+
|
|
419
|
+
faiss::gpu::StandardGpuResources res;
|
|
420
|
+
res.noTempMemory();
|
|
421
|
+
|
|
422
|
+
faiss::gpu::GpuIndexIVFPQConfig config;
|
|
423
|
+
config.device = device;
|
|
424
|
+
config.memorySpace = faiss::gpu::MemorySpace::Unified;
|
|
425
|
+
|
|
426
|
+
faiss::gpu::GpuIndexIVFPQ gpuIndex(&res,
|
|
427
|
+
dim,
|
|
428
|
+
numCentroids,
|
|
429
|
+
codes,
|
|
430
|
+
bitsPerCode,
|
|
431
|
+
faiss::METRIC_L2,
|
|
432
|
+
config);
|
|
433
|
+
gpuIndex.copyFrom(&cpuIndex);
|
|
434
|
+
gpuIndex.setNumProbes(nprobe);
|
|
435
|
+
|
|
436
|
+
faiss::gpu::compareIndices(cpuIndex, gpuIndex,
|
|
437
|
+
numQuery, dim, k, "Unified Memory",
|
|
438
|
+
0.015f,
|
|
439
|
+
0.1f,
|
|
440
|
+
0.015f);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
int main(int argc, char** argv) {
|
|
444
|
+
testing::InitGoogleTest(&argc, argv);
|
|
445
|
+
|
|
446
|
+
// just run with a fixed test seed
|
|
447
|
+
faiss::gpu::setTestSeed(100);
|
|
448
|
+
|
|
449
|
+
return RUN_ALL_TESTS();
|
|
450
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
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/gpu/GpuIndexFlat.h>
|
|
11
|
+
#include <faiss/gpu/StandardGpuResources.h>
|
|
12
|
+
#include <faiss/gpu/utils/DeviceUtils.h>
|
|
13
|
+
#include <faiss/gpu/test/TestUtils.h>
|
|
14
|
+
#include <gtest/gtest.h>
|
|
15
|
+
|
|
16
|
+
// Test to see if we can recover after attempting to allocate too much GPU
|
|
17
|
+
// memory
|
|
18
|
+
TEST(TestGpuMemoryException, AddException) {
|
|
19
|
+
size_t numBrokenAdd = std::numeric_limits<int>::max();
|
|
20
|
+
size_t numRealAdd = 10000;
|
|
21
|
+
size_t devFree = 0;
|
|
22
|
+
size_t devTotal = 0;
|
|
23
|
+
|
|
24
|
+
CUDA_VERIFY(cudaMemGetInfo(&devFree, &devTotal));
|
|
25
|
+
|
|
26
|
+
// Figure out the dimensionality needed to get at least greater than devTotal
|
|
27
|
+
size_t brokenAddDims = ((devTotal / sizeof(float)) / numBrokenAdd) + 1;
|
|
28
|
+
size_t realAddDims = 128;
|
|
29
|
+
|
|
30
|
+
faiss::gpu::StandardGpuResources res;
|
|
31
|
+
|
|
32
|
+
faiss::gpu::GpuIndexFlatConfig config;
|
|
33
|
+
config.device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
|
|
34
|
+
|
|
35
|
+
faiss::gpu::GpuIndexFlatL2
|
|
36
|
+
gpuIndexL2Broken(&res, (int) brokenAddDims, config);
|
|
37
|
+
faiss::gpu::GpuIndexFlatL2
|
|
38
|
+
gpuIndexL2(&res, (int) realAddDims, config);
|
|
39
|
+
faiss::IndexFlatL2
|
|
40
|
+
cpuIndex((int) realAddDims);
|
|
41
|
+
|
|
42
|
+
// Should throw on attempting to allocate too much data
|
|
43
|
+
{
|
|
44
|
+
// allocate memory without initialization
|
|
45
|
+
auto vecs =
|
|
46
|
+
std::unique_ptr<float[]>(new float[numBrokenAdd * brokenAddDims]);
|
|
47
|
+
EXPECT_THROW(gpuIndexL2Broken.add(numBrokenAdd, vecs.get()),
|
|
48
|
+
faiss::FaissException);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Should be able to add a smaller set of data now
|
|
52
|
+
{
|
|
53
|
+
auto vecs = faiss::gpu::randVecs(numRealAdd, realAddDims);
|
|
54
|
+
EXPECT_NO_THROW(gpuIndexL2.add(numRealAdd, vecs.data()));
|
|
55
|
+
cpuIndex.add(numRealAdd, vecs.data());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Should throw on attempting to allocate too much data
|
|
59
|
+
{
|
|
60
|
+
// allocate memory without initialization
|
|
61
|
+
auto vecs =
|
|
62
|
+
std::unique_ptr<float[]>(new float[numBrokenAdd * brokenAddDims]);
|
|
63
|
+
EXPECT_THROW(gpuIndexL2Broken.add(numBrokenAdd, vecs.get()),
|
|
64
|
+
faiss::FaissException);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Should be able to query results from what we had before
|
|
68
|
+
{
|
|
69
|
+
size_t numQuery = 10;
|
|
70
|
+
auto vecs = faiss::gpu::randVecs(numQuery, realAddDims);
|
|
71
|
+
EXPECT_NO_THROW(compareIndices(vecs, cpuIndex, gpuIndexL2,
|
|
72
|
+
numQuery, realAddDims, 50, "",
|
|
73
|
+
6e-3f, 0.1f, 0.015f));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
int main(int argc, char** argv) {
|
|
78
|
+
testing::InitGoogleTest(&argc, argv);
|
|
79
|
+
|
|
80
|
+
// just run with a fixed test seed
|
|
81
|
+
faiss::gpu::setTestSeed(100);
|
|
82
|
+
|
|
83
|
+
return RUN_ALL_TESTS();
|
|
84
|
+
}
|