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,102 @@
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/IndexIVFFlat.h>
10
+ #include <faiss/IndexIVFPQ.h>
11
+ #include <faiss/IndexFlat.h>
12
+ #include <faiss/index_io.h>
13
+ #include <faiss/gpu/test/TestUtils.h>
14
+ #include <vector>
15
+ #include <gflags/gflags.h>
16
+
17
+ // For IVFPQ:
18
+ DEFINE_bool(ivfpq, false, "use IVFPQ encoding");
19
+ DEFINE_int32(codes, 4, "number of PQ codes per vector");
20
+ DEFINE_int32(bits_per_code, 8, "number of bits per PQ code");
21
+
22
+ // For IVFFlat:
23
+ DEFINE_bool(l2, true, "use L2 metric (versus IP metric)");
24
+ DEFINE_bool(ivfflat, false, "use IVF flat encoding");
25
+
26
+ // For both:
27
+ DEFINE_string(out, "/home/jhj/local/index.out", "index file for output");
28
+ DEFINE_int32(dim, 128, "vector dimension");
29
+ DEFINE_int32(num_coarse, 100, "number of coarse centroids");
30
+ DEFINE_int32(num, 100000, "total database size");
31
+ DEFINE_int32(num_train, -1, "number of database vecs to train on");
32
+
33
+ template <typename T>
34
+ void fillAndSave(T& index, int numTrain, int num, int dim) {
35
+ auto trainVecs = faiss::gpu::randVecs(numTrain, dim);
36
+ index.train(numTrain, trainVecs.data());
37
+
38
+ constexpr int kAddChunk = 1000000;
39
+
40
+ for (int i = 0; i < num; i += kAddChunk) {
41
+ int numRemaining = (num - i) < kAddChunk ? (num - i) : kAddChunk;
42
+ auto vecs = faiss::gpu::randVecs(numRemaining, dim);
43
+
44
+ printf("adding at %d: %d\n", i, numRemaining);
45
+ index.add(numRemaining, vecs.data());
46
+ }
47
+
48
+ faiss::write_index(&index, FLAGS_out.c_str());
49
+ }
50
+
51
+ int main(int argc, char** argv) {
52
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
53
+
54
+ // Either ivfpq or ivfflat must be set
55
+ if ((FLAGS_ivfpq && FLAGS_ivfflat) ||
56
+ (!FLAGS_ivfpq && !FLAGS_ivfflat)) {
57
+ printf("must specify either ivfpq or ivfflat\n");
58
+ return 1;
59
+ }
60
+
61
+ auto dim = FLAGS_dim;
62
+ auto numCentroids = FLAGS_num_coarse;
63
+ auto num = FLAGS_num;
64
+ auto numTrain = FLAGS_num_train;
65
+ numTrain = numTrain == -1 ? std::max((num / 4), 1) : numTrain;
66
+ numTrain = std::min(num, numTrain);
67
+
68
+ if (FLAGS_ivfpq) {
69
+ faiss::IndexFlatL2 quantizer(dim);
70
+ faiss::IndexIVFPQ index(&quantizer, dim, numCentroids,
71
+ FLAGS_codes, FLAGS_bits_per_code);
72
+ index.verbose = true;
73
+
74
+ printf("IVFPQ: codes %d bits per code %d\n",
75
+ FLAGS_codes, FLAGS_bits_per_code);
76
+ printf("Lists: %d\n", numCentroids);
77
+ printf("Database: dim %d num vecs %d trained on %d\n", dim, num, numTrain);
78
+ printf("output file: %s\n", FLAGS_out.c_str());
79
+
80
+ fillAndSave(index, numTrain, num, dim);
81
+ } else if (FLAGS_ivfflat) {
82
+ faiss::IndexFlatL2 quantizerL2(dim);
83
+ faiss::IndexFlatIP quantizerIP(dim);
84
+
85
+ faiss::IndexFlat* quantizer = FLAGS_l2 ?
86
+ (faiss::IndexFlat*) &quantizerL2 :
87
+ (faiss::IndexFlat*) &quantizerIP;
88
+
89
+ faiss::IndexIVFFlat index(quantizer, dim, numCentroids,
90
+ FLAGS_l2 ? faiss::METRIC_L2 :
91
+ faiss::METRIC_INNER_PRODUCT);
92
+
93
+ printf("IVFFlat: metric %s\n", FLAGS_l2 ? "L2" : "IP");
94
+ printf("Lists: %d\n", numCentroids);
95
+ printf("Database: dim %d num vecs %d trained on %d\n", dim, num, numTrain);
96
+ printf("output file: %s\n", FLAGS_out.c_str());
97
+
98
+ fillAndSave(index, numTrain, num, dim);
99
+ }
100
+
101
+ return 0;
102
+ }
@@ -0,0 +1,130 @@
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/IndexBinaryFlat.h>
10
+ #include <faiss/gpu/GpuIndexBinaryFlat.h>
11
+ #include <faiss/gpu/StandardGpuResources.h>
12
+ #include <faiss/gpu/utils/DeviceUtils.h>
13
+ #include <faiss/gpu/test/TestUtils.h>
14
+ #include <faiss/utils/utils.h>
15
+ #include <gtest/gtest.h>
16
+ #include <sstream>
17
+ #include <vector>
18
+
19
+ void compareBinaryDist(const std::vector<int>& cpuDist,
20
+ const std::vector<faiss::IndexBinary::idx_t>& cpuLabels,
21
+ const std::vector<int>& gpuDist,
22
+ const std::vector<faiss::IndexBinary::idx_t>& gpuLabels,
23
+ int numQuery,
24
+ int k) {
25
+ for (int i = 0; i < numQuery; ++i) {
26
+ // The index order can be permuted within a group that has the same
27
+ // distance, since this is based on the order in which the algorithm
28
+ // encounters the values. The last set of equivalent distances seen in the
29
+ // min-k might be truncated, so we can't check that set, but all others we
30
+ // can check.
31
+ std::set<faiss::IndexBinary::idx_t> cpuLabelSet;
32
+ std::set<faiss::IndexBinary::idx_t> gpuLabelSet;
33
+
34
+ int curDist = -1;
35
+
36
+ for (int j = 0; j < k; ++j) {
37
+ int idx = i * k + j;
38
+
39
+ if (curDist == -1) {
40
+ curDist = cpuDist[idx];
41
+ }
42
+
43
+ if (curDist != cpuDist[idx]) {
44
+ // Distances must be monotonically increasing
45
+ EXPECT_LT(curDist, cpuDist[idx]);
46
+
47
+ // This is a new set of distances
48
+ EXPECT_EQ(cpuLabelSet, gpuLabelSet);
49
+ curDist = cpuDist[idx];
50
+ cpuLabelSet.clear();
51
+ gpuLabelSet.clear();
52
+ }
53
+
54
+ cpuLabelSet.insert(cpuLabels[idx]);
55
+ gpuLabelSet.insert(gpuLabels[idx]);
56
+
57
+ // Because the distances are reproducible, they must be exactly the same
58
+ EXPECT_EQ(cpuDist[idx], gpuDist[idx]);
59
+ }
60
+ }
61
+ }
62
+
63
+ template <int DimMultiple>
64
+ void testGpuIndexBinaryFlat(int kOverride = -1) {
65
+ faiss::gpu::StandardGpuResources res;
66
+ res.noTempMemory();
67
+
68
+ faiss::gpu::GpuIndexBinaryFlatConfig config;
69
+ config.device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
70
+
71
+ // multiples of 8 and multiples of 32 use different implementations
72
+ int dims = faiss::gpu::randVal(1, 20) * DimMultiple;
73
+ faiss::gpu::GpuIndexBinaryFlat gpuIndex(&res, dims, config);
74
+
75
+ faiss::IndexBinaryFlat cpuIndex(dims);
76
+
77
+ int k = kOverride > 0 ?
78
+ kOverride : faiss::gpu::randVal(1, faiss::gpu::getMaxKSelection());
79
+ int numVecs = faiss::gpu::randVal(k + 1, 20000);
80
+ int numQuery = faiss::gpu::randVal(1, 1000);
81
+
82
+ auto data = faiss::gpu::randBinaryVecs(numVecs, dims);
83
+ gpuIndex.add(numVecs, data.data());
84
+ cpuIndex.add(numVecs, data.data());
85
+
86
+ auto query = faiss::gpu::randBinaryVecs(numQuery, dims);
87
+
88
+ std::vector<int> cpuDist(numQuery * k);
89
+ std::vector<faiss::IndexBinary::idx_t> cpuLabels(numQuery * k);
90
+
91
+ cpuIndex.search(numQuery,
92
+ query.data(),
93
+ k,
94
+ cpuDist.data(),
95
+ cpuLabels.data());
96
+
97
+ std::vector<int> gpuDist(numQuery * k);
98
+ std::vector<faiss::IndexBinary::idx_t> gpuLabels(numQuery * k);
99
+
100
+ gpuIndex.search(numQuery,
101
+ query.data(),
102
+ k,
103
+ gpuDist.data(),
104
+ gpuLabels.data());
105
+
106
+ compareBinaryDist(cpuDist, cpuLabels,
107
+ gpuDist, gpuLabels,
108
+ numQuery, k);
109
+ }
110
+
111
+ TEST(TestGpuIndexBinaryFlat, Test8) {
112
+ for (int tries = 0; tries < 4; ++tries) {
113
+ testGpuIndexBinaryFlat<8>();
114
+ }
115
+ }
116
+
117
+ TEST(TestGpuIndexBinaryFlat, Test32) {
118
+ for (int tries = 0; tries < 4; ++tries) {
119
+ testGpuIndexBinaryFlat<32>();
120
+ }
121
+ }
122
+
123
+ int main(int argc, char** argv) {
124
+ testing::InitGoogleTest(&argc, argv);
125
+
126
+ // just run with a fixed test seed
127
+ faiss::gpu::setTestSeed(100);
128
+
129
+ return RUN_ALL_TESTS();
130
+ }
@@ -0,0 +1,371 @@
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
+ #include <sstream>
16
+ #include <vector>
17
+
18
+ // FIXME: figure out a better way to test fp16
19
+ constexpr float kF16MaxRelErr = 0.07f;
20
+ constexpr float kF32MaxRelErr = 6e-3f;
21
+
22
+ struct TestFlatOptions {
23
+ TestFlatOptions()
24
+ : useL2(true),
25
+ useFloat16(false),
26
+ useTransposed(false),
27
+ numVecsOverride(-1),
28
+ numQueriesOverride(-1),
29
+ kOverride(-1),
30
+ dimOverride(-1) {
31
+ }
32
+
33
+ bool useL2;
34
+ bool useFloat16;
35
+ bool useTransposed;
36
+ int numVecsOverride;
37
+ int numQueriesOverride;
38
+ int kOverride;
39
+ int dimOverride;
40
+ };
41
+
42
+ void testFlat(const TestFlatOptions& opt) {
43
+ int numVecs = opt.numVecsOverride > 0 ?
44
+ opt.numVecsOverride : faiss::gpu::randVal(1000, 20000);
45
+ int dim = opt.dimOverride > 0 ?
46
+ opt.dimOverride : faiss::gpu::randVal(50, 800);
47
+ int numQuery = opt.numQueriesOverride > 0 ?
48
+ opt.numQueriesOverride : faiss::gpu::randVal(1, 512);
49
+
50
+ // Due to loss of precision in a float16 accumulator, for large k,
51
+ // the number of differences is pretty huge. Restrict ourselves to a
52
+ // fairly small `k` for float16
53
+ int k = opt.useFloat16 ?
54
+ std::min(faiss::gpu::randVal(1, 50), numVecs) :
55
+ std::min(faiss::gpu::randVal(1, faiss::gpu::getMaxKSelection()), numVecs);
56
+ if (opt.kOverride > 0) {
57
+ k = opt.kOverride;
58
+ }
59
+
60
+ faiss::IndexFlatIP cpuIndexIP(dim);
61
+ faiss::IndexFlatL2 cpuIndexL2(dim);
62
+
63
+ faiss::IndexFlat* cpuIndex =
64
+ opt.useL2 ? (faiss::IndexFlat*) &cpuIndexL2 :
65
+ (faiss::IndexFlat*) &cpuIndexIP;
66
+
67
+ // Construct on a random device to test multi-device, if we have
68
+ // multiple devices
69
+ int device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
70
+
71
+ faiss::gpu::StandardGpuResources res;
72
+ res.noTempMemory();
73
+
74
+
75
+ faiss::gpu::GpuIndexFlatConfig config;
76
+ config.device = device;
77
+ config.useFloat16 = opt.useFloat16;
78
+ config.storeTransposed = opt.useTransposed;
79
+
80
+ faiss::gpu::GpuIndexFlatIP gpuIndexIP(&res, dim, config);
81
+ faiss::gpu::GpuIndexFlatL2 gpuIndexL2(&res, dim, config);
82
+
83
+ faiss::gpu::GpuIndexFlat* gpuIndex =
84
+ opt.useL2 ? (faiss::gpu::GpuIndexFlat*) &gpuIndexL2 :
85
+ (faiss::gpu::GpuIndexFlat*) &gpuIndexIP;
86
+
87
+ std::vector<float> vecs = faiss::gpu::randVecs(numVecs, dim);
88
+ cpuIndex->add(numVecs, vecs.data());
89
+ gpuIndex->add(numVecs, vecs.data());
90
+
91
+ std::stringstream str;
92
+ str << (opt.useL2 ? "L2" : "IP") << " numVecs " << numVecs
93
+ << " dim " << dim
94
+ << " useFloat16 " << opt.useFloat16
95
+ << " transposed " << opt.useTransposed
96
+ << " numQuery " << numQuery
97
+ << " k " << k;
98
+
99
+ // To some extent, we depend upon the relative error for the test
100
+ // for float16
101
+ faiss::gpu::compareIndices(*cpuIndex, *gpuIndex, numQuery, dim, k, str.str(),
102
+ opt.useFloat16 ? kF16MaxRelErr : kF32MaxRelErr,
103
+ // FIXME: the fp16 bounds are
104
+ // useless when math (the accumulator) is
105
+ // in fp16. Figure out another way to test
106
+ opt.useFloat16 ? 0.99f : 0.1f,
107
+ opt.useFloat16 ? 0.65f : 0.015f);
108
+ }
109
+
110
+ TEST(TestGpuIndexFlat, IP_Float32) {
111
+ for (int tries = 0; tries < 3; ++tries) {
112
+ TestFlatOptions opt;
113
+ opt.useL2 = false;
114
+ opt.useFloat16 = false;
115
+ opt.useTransposed = false;
116
+
117
+ testFlat(opt);
118
+
119
+ opt.useTransposed = true;
120
+ testFlat(opt);
121
+ }
122
+ }
123
+
124
+ TEST(TestGpuIndexFlat, L2_Float32) {
125
+ for (int tries = 0; tries < 3; ++tries) {
126
+ TestFlatOptions opt;
127
+ opt.useL2 = true;
128
+ opt.useFloat16 = false;
129
+ opt.useTransposed = false;
130
+
131
+ testFlat(opt);
132
+
133
+ opt.useTransposed = true;
134
+ testFlat(opt);
135
+ }
136
+ }
137
+
138
+ // test specialized k == 1 codepath
139
+ TEST(TestGpuIndexFlat, L2_Float32_K1) {
140
+ for (int tries = 0; tries < 3; ++tries) {
141
+ TestFlatOptions opt;
142
+ opt.useL2 = true;
143
+ opt.useFloat16 = false;
144
+ opt.useTransposed = false;
145
+ opt.kOverride = 1;
146
+
147
+ testFlat(opt);
148
+ }
149
+ }
150
+
151
+ TEST(TestGpuIndexFlat, IP_Float16) {
152
+ for (int tries = 0; tries < 3; ++tries) {
153
+ TestFlatOptions opt;
154
+ opt.useL2 = false;
155
+ opt.useFloat16 = true;
156
+ opt.useTransposed = false;
157
+
158
+ testFlat(opt);
159
+
160
+ opt.useTransposed = true;
161
+ testFlat(opt);
162
+ }
163
+ }
164
+
165
+ TEST(TestGpuIndexFlat, L2_Float16) {
166
+ for (int tries = 0; tries < 3; ++tries) {
167
+ TestFlatOptions opt;
168
+ opt.useL2 = true;
169
+ opt.useFloat16 = true;
170
+ opt.useTransposed = false;
171
+
172
+ testFlat(opt);
173
+
174
+ opt.useTransposed = true;
175
+ testFlat(opt);
176
+ }
177
+ }
178
+
179
+ // test specialized k == 1 codepath
180
+ TEST(TestGpuIndexFlat, L2_Float16_K1) {
181
+ for (int tries = 0; tries < 3; ++tries) {
182
+ TestFlatOptions opt;
183
+ opt.useL2 = true;
184
+ opt.useFloat16 = true;
185
+ opt.useTransposed = false;
186
+ opt.kOverride = 1;
187
+
188
+ testFlat(opt);
189
+ }
190
+ }
191
+
192
+ // test tiling along a huge vector set
193
+ TEST(TestGpuIndexFlat, L2_Tiling) {
194
+ for (int tries = 0; tries < 2; ++tries) {
195
+ TestFlatOptions opt;
196
+ opt.useL2 = true;
197
+ opt.useFloat16 = false;
198
+ opt.useTransposed = false;
199
+ opt.numVecsOverride = 1000000;
200
+
201
+ // keep the rest of the problem reasonably small
202
+ opt.numQueriesOverride = 4;
203
+ opt.dimOverride = 64;
204
+ opt.kOverride = 64;
205
+
206
+ testFlat(opt);
207
+ }
208
+ }
209
+
210
+ TEST(TestGpuIndexFlat, QueryEmpty) {
211
+ faiss::gpu::StandardGpuResources res;
212
+ res.noTempMemory();
213
+
214
+ faiss::gpu::GpuIndexFlatConfig config;
215
+ config.device = 0;
216
+ config.useFloat16 = false;
217
+ config.storeTransposed = false;
218
+
219
+ int dim = 128;
220
+ faiss::gpu::GpuIndexFlatL2 gpuIndex(&res, dim, config);
221
+
222
+ // Querying an empty index should not blow up, and just return
223
+ // (FLT_MAX, -1)
224
+ int numQuery = 10;
225
+ int k = 50;
226
+ std::vector<float> queries(numQuery * dim, 1.0f);
227
+
228
+ std::vector<float> dist(numQuery * k, 0);
229
+ std::vector<faiss::Index::idx_t> ind(numQuery * k);
230
+
231
+ gpuIndex.search(numQuery, queries.data(), k, dist.data(), ind.data());
232
+
233
+ for (auto d : dist) {
234
+ EXPECT_EQ(d, std::numeric_limits<float>::max());
235
+ }
236
+
237
+ for (auto i : ind) {
238
+ EXPECT_EQ(i, -1);
239
+ }
240
+ }
241
+
242
+ TEST(TestGpuIndexFlat, CopyFrom) {
243
+ int numVecs = faiss::gpu::randVal(100, 200);
244
+ int dim = faiss::gpu::randVal(1, 1000);
245
+
246
+ faiss::IndexFlatL2 cpuIndex(dim);
247
+
248
+ std::vector<float> vecs = faiss::gpu::randVecs(numVecs, dim);
249
+ cpuIndex.add(numVecs, vecs.data());
250
+
251
+ faiss::gpu::StandardGpuResources res;
252
+ res.noTempMemory();
253
+
254
+ // Fill with garbage values
255
+ int device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
256
+
257
+ faiss::gpu::GpuIndexFlatConfig config;
258
+ config.device = 0;
259
+ config.useFloat16 = false;
260
+ config.storeTransposed = false;
261
+
262
+ faiss::gpu::GpuIndexFlatL2 gpuIndex(&res, 2000, config);
263
+ gpuIndex.copyFrom(&cpuIndex);
264
+
265
+ EXPECT_EQ(cpuIndex.ntotal, gpuIndex.ntotal);
266
+ EXPECT_EQ(gpuIndex.ntotal, numVecs);
267
+
268
+ EXPECT_EQ(cpuIndex.d, gpuIndex.d);
269
+ EXPECT_EQ(cpuIndex.d, dim);
270
+
271
+ int idx = faiss::gpu::randVal(0, numVecs - 1);
272
+
273
+ std::vector<float> gpuVals(dim);
274
+ gpuIndex.reconstruct(idx, gpuVals.data());
275
+
276
+ std::vector<float> cpuVals(dim);
277
+ cpuIndex.reconstruct(idx, cpuVals.data());
278
+
279
+ EXPECT_EQ(gpuVals, cpuVals);
280
+ }
281
+
282
+ TEST(TestGpuIndexFlat, CopyTo) {
283
+ faiss::gpu::StandardGpuResources res;
284
+ res.noTempMemory();
285
+
286
+ int numVecs = faiss::gpu::randVal(100, 200);
287
+ int dim = faiss::gpu::randVal(1, 1000);
288
+
289
+ int device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
290
+
291
+ faiss::gpu::GpuIndexFlatConfig config;
292
+ config.device = device;
293
+ config.useFloat16 = false;
294
+ config.storeTransposed = false;
295
+
296
+ faiss::gpu::GpuIndexFlatL2 gpuIndex(&res, dim, config);
297
+
298
+ std::vector<float> vecs = faiss::gpu::randVecs(numVecs, dim);
299
+ gpuIndex.add(numVecs, vecs.data());
300
+
301
+ // Fill with garbage values
302
+ faiss::IndexFlatL2 cpuIndex(2000);
303
+ gpuIndex.copyTo(&cpuIndex);
304
+
305
+ EXPECT_EQ(cpuIndex.ntotal, gpuIndex.ntotal);
306
+ EXPECT_EQ(gpuIndex.ntotal, numVecs);
307
+
308
+ EXPECT_EQ(cpuIndex.d, gpuIndex.d);
309
+ EXPECT_EQ(cpuIndex.d, dim);
310
+
311
+ int idx = faiss::gpu::randVal(0, numVecs - 1);
312
+
313
+ std::vector<float> gpuVals(dim);
314
+ gpuIndex.reconstruct(idx, gpuVals.data());
315
+
316
+ std::vector<float> cpuVals(dim);
317
+ cpuIndex.reconstruct(idx, cpuVals.data());
318
+
319
+ EXPECT_EQ(gpuVals, cpuVals);
320
+ }
321
+
322
+ TEST(TestGpuIndexFlat, UnifiedMemory) {
323
+ // Construct on a random device to test multi-device, if we have
324
+ // multiple devices
325
+ int device = faiss::gpu::randVal(0, faiss::gpu::getNumDevices() - 1);
326
+
327
+ if (!faiss::gpu::getFullUnifiedMemSupport(device)) {
328
+ return;
329
+ }
330
+
331
+ int dim = 256;
332
+
333
+ // FIXME: GpuIndexFlat doesn't support > 2^31 (vecs * dims) due to
334
+ // kernel indexing, so we can't test unified memory for memory
335
+ // oversubscription.
336
+ size_t numVecs = 50000;
337
+ int numQuery = 10;
338
+ int k = 10;
339
+
340
+ faiss::IndexFlatL2 cpuIndexL2(dim);
341
+
342
+ faiss::gpu::StandardGpuResources res;
343
+ res.noTempMemory();
344
+
345
+ faiss::gpu::GpuIndexFlatConfig config;
346
+ config.device = device;
347
+ config.memorySpace = faiss::gpu::MemorySpace::Unified;
348
+
349
+ faiss::gpu::GpuIndexFlatL2 gpuIndexL2(&res, dim, config);
350
+
351
+ std::vector<float> vecs = faiss::gpu::randVecs(numVecs, dim);
352
+ cpuIndexL2.add(numVecs, vecs.data());
353
+ gpuIndexL2.add(numVecs, vecs.data());
354
+
355
+ // To some extent, we depend upon the relative error for the test
356
+ // for float16
357
+ faiss::gpu::compareIndices(cpuIndexL2, gpuIndexL2,
358
+ numQuery, dim, k, "Unified Memory",
359
+ kF32MaxRelErr,
360
+ 0.1f,
361
+ 0.015f);
362
+ }
363
+
364
+ int main(int argc, char** argv) {
365
+ testing::InitGoogleTest(&argc, argv);
366
+
367
+ // just run with a fixed test seed
368
+ faiss::gpu::setTestSeed(100);
369
+
370
+ return RUN_ALL_TESTS();
371
+ }