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.
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
+ }