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