faiss 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (226) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +103 -3
  4. data/ext/faiss/ext.cpp +99 -32
  5. data/ext/faiss/extconf.rb +12 -2
  6. data/lib/faiss/ext.bundle +0 -0
  7. data/lib/faiss/index.rb +3 -3
  8. data/lib/faiss/index_binary.rb +3 -3
  9. data/lib/faiss/kmeans.rb +1 -1
  10. data/lib/faiss/pca_matrix.rb +2 -2
  11. data/lib/faiss/product_quantizer.rb +3 -3
  12. data/lib/faiss/version.rb +1 -1
  13. data/vendor/faiss/AutoTune.cpp +719 -0
  14. data/vendor/faiss/AutoTune.h +212 -0
  15. data/vendor/faiss/Clustering.cpp +261 -0
  16. data/vendor/faiss/Clustering.h +101 -0
  17. data/vendor/faiss/IVFlib.cpp +339 -0
  18. data/vendor/faiss/IVFlib.h +132 -0
  19. data/vendor/faiss/Index.cpp +171 -0
  20. data/vendor/faiss/Index.h +261 -0
  21. data/vendor/faiss/Index2Layer.cpp +437 -0
  22. data/vendor/faiss/Index2Layer.h +85 -0
  23. data/vendor/faiss/IndexBinary.cpp +77 -0
  24. data/vendor/faiss/IndexBinary.h +163 -0
  25. data/vendor/faiss/IndexBinaryFlat.cpp +83 -0
  26. data/vendor/faiss/IndexBinaryFlat.h +54 -0
  27. data/vendor/faiss/IndexBinaryFromFloat.cpp +78 -0
  28. data/vendor/faiss/IndexBinaryFromFloat.h +52 -0
  29. data/vendor/faiss/IndexBinaryHNSW.cpp +325 -0
  30. data/vendor/faiss/IndexBinaryHNSW.h +56 -0
  31. data/vendor/faiss/IndexBinaryIVF.cpp +671 -0
  32. data/vendor/faiss/IndexBinaryIVF.h +211 -0
  33. data/vendor/faiss/IndexFlat.cpp +508 -0
  34. data/vendor/faiss/IndexFlat.h +175 -0
  35. data/vendor/faiss/IndexHNSW.cpp +1090 -0
  36. data/vendor/faiss/IndexHNSW.h +170 -0
  37. data/vendor/faiss/IndexIVF.cpp +909 -0
  38. data/vendor/faiss/IndexIVF.h +353 -0
  39. data/vendor/faiss/IndexIVFFlat.cpp +502 -0
  40. data/vendor/faiss/IndexIVFFlat.h +118 -0
  41. data/vendor/faiss/IndexIVFPQ.cpp +1207 -0
  42. data/vendor/faiss/IndexIVFPQ.h +161 -0
  43. data/vendor/faiss/IndexIVFPQR.cpp +219 -0
  44. data/vendor/faiss/IndexIVFPQR.h +65 -0
  45. data/vendor/faiss/IndexIVFSpectralHash.cpp +331 -0
  46. data/vendor/faiss/IndexIVFSpectralHash.h +75 -0
  47. data/vendor/faiss/IndexLSH.cpp +225 -0
  48. data/vendor/faiss/IndexLSH.h +87 -0
  49. data/vendor/faiss/IndexLattice.cpp +143 -0
  50. data/vendor/faiss/IndexLattice.h +68 -0
  51. data/vendor/faiss/IndexPQ.cpp +1188 -0
  52. data/vendor/faiss/IndexPQ.h +199 -0
  53. data/vendor/faiss/IndexPreTransform.cpp +288 -0
  54. data/vendor/faiss/IndexPreTransform.h +91 -0
  55. data/vendor/faiss/IndexReplicas.cpp +123 -0
  56. data/vendor/faiss/IndexReplicas.h +76 -0
  57. data/vendor/faiss/IndexScalarQuantizer.cpp +317 -0
  58. data/vendor/faiss/IndexScalarQuantizer.h +127 -0
  59. data/vendor/faiss/IndexShards.cpp +317 -0
  60. data/vendor/faiss/IndexShards.h +100 -0
  61. data/vendor/faiss/InvertedLists.cpp +623 -0
  62. data/vendor/faiss/InvertedLists.h +334 -0
  63. data/vendor/faiss/LICENSE +21 -0
  64. data/vendor/faiss/MatrixStats.cpp +252 -0
  65. data/vendor/faiss/MatrixStats.h +62 -0
  66. data/vendor/faiss/MetaIndexes.cpp +351 -0
  67. data/vendor/faiss/MetaIndexes.h +126 -0
  68. data/vendor/faiss/OnDiskInvertedLists.cpp +674 -0
  69. data/vendor/faiss/OnDiskInvertedLists.h +127 -0
  70. data/vendor/faiss/VectorTransform.cpp +1157 -0
  71. data/vendor/faiss/VectorTransform.h +322 -0
  72. data/vendor/faiss/c_api/AutoTune_c.cpp +83 -0
  73. data/vendor/faiss/c_api/AutoTune_c.h +64 -0
  74. data/vendor/faiss/c_api/Clustering_c.cpp +139 -0
  75. data/vendor/faiss/c_api/Clustering_c.h +117 -0
  76. data/vendor/faiss/c_api/IndexFlat_c.cpp +140 -0
  77. data/vendor/faiss/c_api/IndexFlat_c.h +115 -0
  78. data/vendor/faiss/c_api/IndexIVFFlat_c.cpp +64 -0
  79. data/vendor/faiss/c_api/IndexIVFFlat_c.h +58 -0
  80. data/vendor/faiss/c_api/IndexIVF_c.cpp +92 -0
  81. data/vendor/faiss/c_api/IndexIVF_c.h +135 -0
  82. data/vendor/faiss/c_api/IndexLSH_c.cpp +37 -0
  83. data/vendor/faiss/c_api/IndexLSH_c.h +40 -0
  84. data/vendor/faiss/c_api/IndexShards_c.cpp +44 -0
  85. data/vendor/faiss/c_api/IndexShards_c.h +42 -0
  86. data/vendor/faiss/c_api/Index_c.cpp +105 -0
  87. data/vendor/faiss/c_api/Index_c.h +183 -0
  88. data/vendor/faiss/c_api/MetaIndexes_c.cpp +49 -0
  89. data/vendor/faiss/c_api/MetaIndexes_c.h +49 -0
  90. data/vendor/faiss/c_api/clone_index_c.cpp +23 -0
  91. data/vendor/faiss/c_api/clone_index_c.h +32 -0
  92. data/vendor/faiss/c_api/error_c.h +42 -0
  93. data/vendor/faiss/c_api/error_impl.cpp +27 -0
  94. data/vendor/faiss/c_api/error_impl.h +16 -0
  95. data/vendor/faiss/c_api/faiss_c.h +58 -0
  96. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +96 -0
  97. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.h +56 -0
  98. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +52 -0
  99. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.h +68 -0
  100. data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +17 -0
  101. data/vendor/faiss/c_api/gpu/GpuIndex_c.h +30 -0
  102. data/vendor/faiss/c_api/gpu/GpuIndicesOptions_c.h +38 -0
  103. data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +86 -0
  104. data/vendor/faiss/c_api/gpu/GpuResources_c.h +66 -0
  105. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +54 -0
  106. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.h +53 -0
  107. data/vendor/faiss/c_api/gpu/macros_impl.h +42 -0
  108. data/vendor/faiss/c_api/impl/AuxIndexStructures_c.cpp +220 -0
  109. data/vendor/faiss/c_api/impl/AuxIndexStructures_c.h +149 -0
  110. data/vendor/faiss/c_api/index_factory_c.cpp +26 -0
  111. data/vendor/faiss/c_api/index_factory_c.h +30 -0
  112. data/vendor/faiss/c_api/index_io_c.cpp +42 -0
  113. data/vendor/faiss/c_api/index_io_c.h +50 -0
  114. data/vendor/faiss/c_api/macros_impl.h +110 -0
  115. data/vendor/faiss/clone_index.cpp +147 -0
  116. data/vendor/faiss/clone_index.h +38 -0
  117. data/vendor/faiss/demos/demo_imi_flat.cpp +151 -0
  118. data/vendor/faiss/demos/demo_imi_pq.cpp +199 -0
  119. data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +146 -0
  120. data/vendor/faiss/demos/demo_sift1M.cpp +252 -0
  121. data/vendor/faiss/gpu/GpuAutoTune.cpp +95 -0
  122. data/vendor/faiss/gpu/GpuAutoTune.h +27 -0
  123. data/vendor/faiss/gpu/GpuCloner.cpp +403 -0
  124. data/vendor/faiss/gpu/GpuCloner.h +82 -0
  125. data/vendor/faiss/gpu/GpuClonerOptions.cpp +28 -0
  126. data/vendor/faiss/gpu/GpuClonerOptions.h +53 -0
  127. data/vendor/faiss/gpu/GpuDistance.h +52 -0
  128. data/vendor/faiss/gpu/GpuFaissAssert.h +29 -0
  129. data/vendor/faiss/gpu/GpuIndex.h +148 -0
  130. data/vendor/faiss/gpu/GpuIndexBinaryFlat.h +89 -0
  131. data/vendor/faiss/gpu/GpuIndexFlat.h +190 -0
  132. data/vendor/faiss/gpu/GpuIndexIVF.h +89 -0
  133. data/vendor/faiss/gpu/GpuIndexIVFFlat.h +85 -0
  134. data/vendor/faiss/gpu/GpuIndexIVFPQ.h +143 -0
  135. data/vendor/faiss/gpu/GpuIndexIVFScalarQuantizer.h +100 -0
  136. data/vendor/faiss/gpu/GpuIndicesOptions.h +30 -0
  137. data/vendor/faiss/gpu/GpuResources.cpp +52 -0
  138. data/vendor/faiss/gpu/GpuResources.h +73 -0
  139. data/vendor/faiss/gpu/StandardGpuResources.cpp +295 -0
  140. data/vendor/faiss/gpu/StandardGpuResources.h +114 -0
  141. data/vendor/faiss/gpu/impl/RemapIndices.cpp +43 -0
  142. data/vendor/faiss/gpu/impl/RemapIndices.h +24 -0
  143. data/vendor/faiss/gpu/perf/IndexWrapper-inl.h +71 -0
  144. data/vendor/faiss/gpu/perf/IndexWrapper.h +39 -0
  145. data/vendor/faiss/gpu/perf/PerfClustering.cpp +115 -0
  146. data/vendor/faiss/gpu/perf/PerfIVFPQAdd.cpp +139 -0
  147. data/vendor/faiss/gpu/perf/WriteIndex.cpp +102 -0
  148. data/vendor/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +130 -0
  149. data/vendor/faiss/gpu/test/TestGpuIndexFlat.cpp +371 -0
  150. data/vendor/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +550 -0
  151. data/vendor/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +450 -0
  152. data/vendor/faiss/gpu/test/TestGpuMemoryException.cpp +84 -0
  153. data/vendor/faiss/gpu/test/TestUtils.cpp +315 -0
  154. data/vendor/faiss/gpu/test/TestUtils.h +93 -0
  155. data/vendor/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +159 -0
  156. data/vendor/faiss/gpu/utils/DeviceMemory.cpp +77 -0
  157. data/vendor/faiss/gpu/utils/DeviceMemory.h +71 -0
  158. data/vendor/faiss/gpu/utils/DeviceUtils.h +185 -0
  159. data/vendor/faiss/gpu/utils/MemorySpace.cpp +89 -0
  160. data/vendor/faiss/gpu/utils/MemorySpace.h +44 -0
  161. data/vendor/faiss/gpu/utils/StackDeviceMemory.cpp +239 -0
  162. data/vendor/faiss/gpu/utils/StackDeviceMemory.h +129 -0
  163. data/vendor/faiss/gpu/utils/StaticUtils.h +83 -0
  164. data/vendor/faiss/gpu/utils/Timer.cpp +60 -0
  165. data/vendor/faiss/gpu/utils/Timer.h +52 -0
  166. data/vendor/faiss/impl/AuxIndexStructures.cpp +305 -0
  167. data/vendor/faiss/impl/AuxIndexStructures.h +246 -0
  168. data/vendor/faiss/impl/FaissAssert.h +95 -0
  169. data/vendor/faiss/impl/FaissException.cpp +66 -0
  170. data/vendor/faiss/impl/FaissException.h +71 -0
  171. data/vendor/faiss/impl/HNSW.cpp +818 -0
  172. data/vendor/faiss/impl/HNSW.h +275 -0
  173. data/vendor/faiss/impl/PolysemousTraining.cpp +953 -0
  174. data/vendor/faiss/impl/PolysemousTraining.h +158 -0
  175. data/vendor/faiss/impl/ProductQuantizer.cpp +876 -0
  176. data/vendor/faiss/impl/ProductQuantizer.h +242 -0
  177. data/vendor/faiss/impl/ScalarQuantizer.cpp +1628 -0
  178. data/vendor/faiss/impl/ScalarQuantizer.h +120 -0
  179. data/vendor/faiss/impl/ThreadedIndex-inl.h +192 -0
  180. data/vendor/faiss/impl/ThreadedIndex.h +80 -0
  181. data/vendor/faiss/impl/index_read.cpp +793 -0
  182. data/vendor/faiss/impl/index_write.cpp +558 -0
  183. data/vendor/faiss/impl/io.cpp +142 -0
  184. data/vendor/faiss/impl/io.h +98 -0
  185. data/vendor/faiss/impl/lattice_Zn.cpp +712 -0
  186. data/vendor/faiss/impl/lattice_Zn.h +199 -0
  187. data/vendor/faiss/index_factory.cpp +392 -0
  188. data/vendor/faiss/index_factory.h +25 -0
  189. data/vendor/faiss/index_io.h +75 -0
  190. data/vendor/faiss/misc/test_blas.cpp +84 -0
  191. data/vendor/faiss/tests/test_binary_flat.cpp +64 -0
  192. data/vendor/faiss/tests/test_dealloc_invlists.cpp +183 -0
  193. data/vendor/faiss/tests/test_ivfpq_codec.cpp +67 -0
  194. data/vendor/faiss/tests/test_ivfpq_indexing.cpp +98 -0
  195. data/vendor/faiss/tests/test_lowlevel_ivf.cpp +566 -0
  196. data/vendor/faiss/tests/test_merge.cpp +258 -0
  197. data/vendor/faiss/tests/test_omp_threads.cpp +14 -0
  198. data/vendor/faiss/tests/test_ondisk_ivf.cpp +220 -0
  199. data/vendor/faiss/tests/test_pairs_decoding.cpp +189 -0
  200. data/vendor/faiss/tests/test_params_override.cpp +231 -0
  201. data/vendor/faiss/tests/test_pq_encoding.cpp +98 -0
  202. data/vendor/faiss/tests/test_sliding_ivf.cpp +240 -0
  203. data/vendor/faiss/tests/test_threaded_index.cpp +253 -0
  204. data/vendor/faiss/tests/test_transfer_invlists.cpp +159 -0
  205. data/vendor/faiss/tutorial/cpp/1-Flat.cpp +98 -0
  206. data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +81 -0
  207. data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +93 -0
  208. data/vendor/faiss/tutorial/cpp/4-GPU.cpp +119 -0
  209. data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +99 -0
  210. data/vendor/faiss/utils/Heap.cpp +122 -0
  211. data/vendor/faiss/utils/Heap.h +495 -0
  212. data/vendor/faiss/utils/WorkerThread.cpp +126 -0
  213. data/vendor/faiss/utils/WorkerThread.h +61 -0
  214. data/vendor/faiss/utils/distances.cpp +765 -0
  215. data/vendor/faiss/utils/distances.h +243 -0
  216. data/vendor/faiss/utils/distances_simd.cpp +809 -0
  217. data/vendor/faiss/utils/extra_distances.cpp +336 -0
  218. data/vendor/faiss/utils/extra_distances.h +54 -0
  219. data/vendor/faiss/utils/hamming-inl.h +472 -0
  220. data/vendor/faiss/utils/hamming.cpp +792 -0
  221. data/vendor/faiss/utils/hamming.h +220 -0
  222. data/vendor/faiss/utils/random.cpp +192 -0
  223. data/vendor/faiss/utils/random.h +60 -0
  224. data/vendor/faiss/utils/utils.cpp +783 -0
  225. data/vendor/faiss/utils/utils.h +181 -0
  226. 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
+ }