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,258 @@
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
+ #include <cstdio>
9
+ #include <cstdlib>
10
+
11
+ #include <gtest/gtest.h>
12
+
13
+ #include <faiss/IndexIVFFlat.h>
14
+ #include <faiss/IndexIVFPQ.h>
15
+ #include <faiss/IndexFlat.h>
16
+ #include <faiss/MetaIndexes.h>
17
+ #include <faiss/impl/FaissAssert.h>
18
+ #include <faiss/IndexPreTransform.h>
19
+ #include <faiss/OnDiskInvertedLists.h>
20
+ #include <faiss/IVFlib.h>
21
+
22
+
23
+ namespace {
24
+
25
+
26
+ struct Tempfilename {
27
+
28
+ static pthread_mutex_t mutex;
29
+
30
+ std::string filename;
31
+
32
+ Tempfilename (const char *prefix = nullptr) {
33
+ pthread_mutex_lock (&mutex);
34
+ char *cfname = tempnam (nullptr, prefix);
35
+ filename = cfname;
36
+ free(cfname);
37
+ pthread_mutex_unlock (&mutex);
38
+ }
39
+
40
+ ~Tempfilename () {
41
+ if (access (filename.c_str(), F_OK)) {
42
+ unlink (filename.c_str());
43
+ }
44
+ }
45
+
46
+ const char *c_str() {
47
+ return filename.c_str();
48
+ }
49
+
50
+ };
51
+
52
+ pthread_mutex_t Tempfilename::mutex = PTHREAD_MUTEX_INITIALIZER;
53
+
54
+
55
+ typedef faiss::Index::idx_t idx_t;
56
+
57
+ // parameters to use for the test
58
+ int d = 64;
59
+ size_t nb = 1000;
60
+ size_t nq = 100;
61
+ int nindex = 4;
62
+ int k = 10;
63
+ int nlist = 40;
64
+
65
+ struct CommonData {
66
+
67
+ std::vector <float> database;
68
+ std::vector <float> queries;
69
+ std::vector<idx_t> ids;
70
+ faiss::IndexFlatL2 quantizer;
71
+
72
+ CommonData(): database (nb * d), queries (nq * d), ids(nb), quantizer (d) {
73
+
74
+ for (size_t i = 0; i < nb * d; i++) {
75
+ database[i] = drand48();
76
+ }
77
+ for (size_t i = 0; i < nq * d; i++) {
78
+ queries[i] = drand48();
79
+ }
80
+ for (int i = 0; i < nb; i++) {
81
+ ids[i] = 123 + 456 * i;
82
+ }
83
+ { // just to train the quantizer
84
+ faiss::IndexIVFFlat iflat (&quantizer, d, nlist);
85
+ iflat.train(nb, database.data());
86
+ }
87
+ }
88
+ };
89
+
90
+ CommonData cd;
91
+
92
+ /// perform a search on shards, then merge and search again and
93
+ /// compare results.
94
+ int compare_merged (faiss::IndexShards *index_shards, bool shift_ids,
95
+ bool standard_merge = true)
96
+ {
97
+
98
+ std::vector<idx_t> refI(k * nq);
99
+ std::vector<float> refD(k * nq);
100
+
101
+ index_shards->search(nq, cd.queries.data(), k, refD.data(), refI.data());
102
+ Tempfilename filename;
103
+
104
+ std::vector<idx_t> newI(k * nq);
105
+ std::vector<float> newD(k * nq);
106
+
107
+ if (standard_merge) {
108
+
109
+ for (int i = 1; i < nindex; i++) {
110
+ faiss::ivflib::merge_into(
111
+ index_shards->at(0), index_shards->at(i),
112
+ shift_ids);
113
+ }
114
+
115
+ index_shards->sync_with_shard_indexes();
116
+ } else {
117
+ std::vector<const faiss::InvertedLists *> lists;
118
+ faiss::IndexIVF *index0 = nullptr;
119
+ size_t ntotal = 0;
120
+ for (int i = 0; i < nindex; i++) {
121
+ auto index_ivf = dynamic_cast<faiss::IndexIVF*>(index_shards->at(i));
122
+ assert (index_ivf);
123
+ if (i == 0) {
124
+ index0 = index_ivf;
125
+ }
126
+ lists.push_back (index_ivf->invlists);
127
+ ntotal += index_ivf->ntotal;
128
+ }
129
+
130
+ auto il = new faiss::OnDiskInvertedLists(
131
+ index0->nlist, index0->code_size,
132
+ filename.c_str());
133
+
134
+ il->merge_from(lists.data(), lists.size());
135
+
136
+ index0->replace_invlists(il, true);
137
+ index0->ntotal = ntotal;
138
+ }
139
+ // search only on first index
140
+ index_shards->at(0)->search(nq, cd.queries.data(),
141
+ k, newD.data(), newI.data());
142
+
143
+ size_t ndiff = 0;
144
+ for (size_t i = 0; i < k * nq; i++) {
145
+ if (refI[i] != newI[i]) {
146
+ ndiff ++;
147
+ }
148
+ }
149
+ return ndiff;
150
+ }
151
+
152
+ } // namespace
153
+
154
+
155
+ // test on IVFFlat with implicit numbering
156
+ TEST(MERGE, merge_flat_no_ids) {
157
+ faiss::IndexShards index_shards(d);
158
+ index_shards.own_fields = true;
159
+ for (int i = 0; i < nindex; i++) {
160
+ index_shards.add_shard (
161
+ new faiss::IndexIVFFlat (&cd.quantizer, d, nlist));
162
+ }
163
+ EXPECT_TRUE(index_shards.is_trained);
164
+ index_shards.add(nb, cd.database.data());
165
+ size_t prev_ntotal = index_shards.ntotal;
166
+ int ndiff = compare_merged(&index_shards, true);
167
+ EXPECT_EQ (prev_ntotal, index_shards.ntotal);
168
+ EXPECT_EQ(0, ndiff);
169
+ }
170
+
171
+
172
+ // test on IVFFlat, explicit ids
173
+ TEST(MERGE, merge_flat) {
174
+ faiss::IndexShards index_shards(d, false, false);
175
+ index_shards.own_fields = true;
176
+
177
+ for (int i = 0; i < nindex; i++) {
178
+ index_shards.add_shard (
179
+ new faiss::IndexIVFFlat (&cd.quantizer, d, nlist));
180
+ }
181
+
182
+ EXPECT_TRUE(index_shards.is_trained);
183
+ index_shards.add_with_ids(nb, cd.database.data(), cd.ids.data());
184
+ int ndiff = compare_merged(&index_shards, false);
185
+ EXPECT_GE(0, ndiff);
186
+ }
187
+
188
+ // test on IVFFlat and a VectorTransform
189
+ TEST(MERGE, merge_flat_vt) {
190
+ faiss::IndexShards index_shards(d, false, false);
191
+ index_shards.own_fields = true;
192
+
193
+ // here we have to retrain because of the vectorTransform
194
+ faiss::RandomRotationMatrix rot(d, d);
195
+ rot.init(1234);
196
+ faiss::IndexFlatL2 quantizer (d);
197
+
198
+ { // just to train the quantizer
199
+ faiss::IndexIVFFlat iflat (&quantizer, d, nlist);
200
+ faiss::IndexPreTransform ipt (&rot, &iflat);
201
+ ipt.train(nb, cd.database.data());
202
+ }
203
+
204
+ for (int i = 0; i < nindex; i++) {
205
+ faiss::IndexPreTransform * ipt = new faiss::IndexPreTransform (
206
+ new faiss::RandomRotationMatrix (rot),
207
+ new faiss::IndexIVFFlat (&quantizer, d, nlist)
208
+ );
209
+ ipt->own_fields = true;
210
+ index_shards.add_shard (ipt);
211
+ }
212
+ EXPECT_TRUE(index_shards.is_trained);
213
+ index_shards.add_with_ids(nb, cd.database.data(), cd.ids.data());
214
+ size_t prev_ntotal = index_shards.ntotal;
215
+ int ndiff = compare_merged(&index_shards, false);
216
+ EXPECT_EQ (prev_ntotal, index_shards.ntotal);
217
+ EXPECT_GE(0, ndiff);
218
+ }
219
+
220
+
221
+ // put the merged invfile on disk
222
+ TEST(MERGE, merge_flat_ondisk) {
223
+ faiss::IndexShards index_shards(d, false, false);
224
+ index_shards.own_fields = true;
225
+ Tempfilename filename;
226
+
227
+ for (int i = 0; i < nindex; i++) {
228
+ auto ivf = new faiss::IndexIVFFlat (&cd.quantizer, d, nlist);
229
+ if (i == 0) {
230
+ auto il = new faiss::OnDiskInvertedLists (
231
+ ivf->nlist, ivf->code_size,
232
+ filename.c_str());
233
+ ivf->replace_invlists(il, true);
234
+ }
235
+ index_shards.add_shard (ivf);
236
+ }
237
+
238
+ EXPECT_TRUE(index_shards.is_trained);
239
+ index_shards.add_with_ids(nb, cd.database.data(), cd.ids.data());
240
+ int ndiff = compare_merged(&index_shards, false);
241
+
242
+ EXPECT_EQ(ndiff, 0);
243
+ }
244
+
245
+ // now use ondisk specific merge
246
+ TEST(MERGE, merge_flat_ondisk_2) {
247
+ faiss::IndexShards index_shards(d, false, false);
248
+ index_shards.own_fields = true;
249
+
250
+ for (int i = 0; i < nindex; i++) {
251
+ index_shards.add_shard (
252
+ new faiss::IndexIVFFlat (&cd.quantizer, d, nlist));
253
+ }
254
+ EXPECT_TRUE(index_shards.is_trained);
255
+ index_shards.add_with_ids(nb, cd.database.data(), cd.ids.data());
256
+ int ndiff = compare_merged(&index_shards, false, false);
257
+ EXPECT_GE(0, ndiff);
258
+ }
@@ -0,0 +1,14 @@
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
+ #include <gtest/gtest.h>
9
+
10
+ #include <faiss/utils/utils.h>
11
+
12
+ TEST(Threading, openmp) {
13
+ EXPECT_TRUE(faiss::check_openmp());
14
+ }
@@ -0,0 +1,220 @@
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
+ #include <cstdio>
9
+ #include <cstdlib>
10
+
11
+ #include <omp.h>
12
+
13
+ #include <unordered_map>
14
+ #include <pthread.h>
15
+
16
+ #include <gtest/gtest.h>
17
+
18
+ #include <faiss/OnDiskInvertedLists.h>
19
+ #include <faiss/IndexIVFFlat.h>
20
+ #include <faiss/IndexFlat.h>
21
+ #include <faiss/utils/random.h>
22
+ #include <faiss/index_io.h>
23
+
24
+
25
+ namespace {
26
+
27
+ struct Tempfilename {
28
+
29
+ static pthread_mutex_t mutex;
30
+
31
+ std::string filename;
32
+
33
+ Tempfilename (const char *prefix = nullptr) {
34
+ pthread_mutex_lock (&mutex);
35
+ char *cfname = tempnam (nullptr, prefix);
36
+ filename = cfname;
37
+ free(cfname);
38
+ pthread_mutex_unlock (&mutex);
39
+ }
40
+
41
+ ~Tempfilename () {
42
+ if (access (filename.c_str(), F_OK)) {
43
+ unlink (filename.c_str());
44
+ }
45
+ }
46
+
47
+ const char *c_str() {
48
+ return filename.c_str();
49
+ }
50
+
51
+ };
52
+
53
+ pthread_mutex_t Tempfilename::mutex = PTHREAD_MUTEX_INITIALIZER;
54
+
55
+ } // namespace
56
+
57
+
58
+ TEST(ONDISK, make_invlists) {
59
+ int nlist = 100;
60
+ int code_size = 32;
61
+ int nadd = 1000000;
62
+ std::unordered_map<int, int> listnos;
63
+
64
+ Tempfilename filename;
65
+
66
+ faiss::OnDiskInvertedLists ivf (
67
+ nlist, code_size,
68
+ filename.c_str());
69
+
70
+ {
71
+ std::vector<uint8_t> code(32);
72
+ for (int i = 0; i < nadd; i++) {
73
+ double d = drand48();
74
+ int list_no = int(nlist * d * d); // skewed distribution
75
+ int * ar = (int*)code.data();
76
+ ar[0] = i;
77
+ ar[1] = list_no;
78
+ ivf.add_entry (list_no, i, code.data());
79
+ listnos[i] = list_no;
80
+ }
81
+ }
82
+
83
+ int ntot = 0;
84
+ for (int i = 0; i < nlist; i++) {
85
+ int size = ivf.list_size(i);
86
+ const faiss::Index::idx_t *ids = ivf.get_ids (i);
87
+ const uint8_t *codes = ivf.get_codes (i);
88
+ for (int j = 0; j < size; j++) {
89
+ faiss::Index::idx_t id = ids[j];
90
+ const int * ar = (const int*)&codes[code_size * j];
91
+ EXPECT_EQ (ar[0], id);
92
+ EXPECT_EQ (ar[1], i);
93
+ EXPECT_EQ (listnos[id], i);
94
+ ntot ++;
95
+ }
96
+ }
97
+ EXPECT_EQ (ntot, nadd);
98
+ };
99
+
100
+
101
+ TEST(ONDISK, test_add) {
102
+ int d = 8;
103
+ int nlist = 30, nq = 200, nb = 1500, k = 10;
104
+ faiss::IndexFlatL2 quantizer(d);
105
+ {
106
+ std::vector<float> x(d * nlist);
107
+ faiss::float_rand(x.data(), d * nlist, 12345);
108
+ quantizer.add(nlist, x.data());
109
+ }
110
+ std::vector<float> xb(d * nb);
111
+ faiss::float_rand(xb.data(), d * nb, 23456);
112
+
113
+ faiss::IndexIVFFlat index(&quantizer, d, nlist);
114
+ index.add(nb, xb.data());
115
+
116
+ std::vector<float> xq(d * nb);
117
+ faiss::float_rand(xq.data(), d * nq, 34567);
118
+
119
+ std::vector<float> ref_D (nq * k);
120
+ std::vector<faiss::Index::idx_t> ref_I (nq * k);
121
+
122
+ index.search (nq, xq.data(), k,
123
+ ref_D.data(), ref_I.data());
124
+
125
+ Tempfilename filename, filename2;
126
+
127
+ // test add + search
128
+ {
129
+ faiss::IndexIVFFlat index2(&quantizer, d, nlist);
130
+
131
+ faiss::OnDiskInvertedLists ivf (
132
+ index.nlist, index.code_size,
133
+ filename.c_str());
134
+
135
+ index2.replace_invlists(&ivf);
136
+
137
+ index2.add(nb, xb.data());
138
+
139
+ std::vector<float> new_D (nq * k);
140
+ std::vector<faiss::Index::idx_t> new_I (nq * k);
141
+
142
+ index2.search (nq, xq.data(), k,
143
+ new_D.data(), new_I.data());
144
+
145
+ EXPECT_EQ (ref_D, new_D);
146
+ EXPECT_EQ (ref_I, new_I);
147
+
148
+ write_index(&index2, filename2.c_str());
149
+
150
+ }
151
+
152
+ // test io
153
+ {
154
+ faiss::Index *index3 = faiss::read_index(filename2.c_str());
155
+
156
+ std::vector<float> new_D (nq * k);
157
+ std::vector<faiss::Index::idx_t> new_I (nq * k);
158
+
159
+ index3->search (nq, xq.data(), k,
160
+ new_D.data(), new_I.data());
161
+
162
+ EXPECT_EQ (ref_D, new_D);
163
+ EXPECT_EQ (ref_I, new_I);
164
+
165
+ delete index3;
166
+ }
167
+
168
+ };
169
+
170
+
171
+
172
+ // WARN this thest will run multithreaded only in opt mode
173
+ TEST(ONDISK, make_invlists_threaded) {
174
+ int nlist = 100;
175
+ int code_size = 32;
176
+ int nadd = 1000000;
177
+
178
+ Tempfilename filename;
179
+
180
+ faiss::OnDiskInvertedLists ivf (
181
+ nlist, code_size,
182
+ filename.c_str());
183
+
184
+ std::vector<int> list_nos (nadd);
185
+
186
+ for (int i = 0; i < nadd; i++) {
187
+ double d = drand48();
188
+ list_nos[i] = int(nlist * d * d); // skewed distribution
189
+ }
190
+
191
+ #pragma omp parallel
192
+ {
193
+ std::vector<uint8_t> code(32);
194
+ #pragma omp for
195
+ for (int i = 0; i < nadd; i++) {
196
+ int list_no = list_nos[i];
197
+ int * ar = (int*)code.data();
198
+ ar[0] = i;
199
+ ar[1] = list_no;
200
+ ivf.add_entry (list_no, i, code.data());
201
+ }
202
+ }
203
+
204
+ int ntot = 0;
205
+ for (int i = 0; i < nlist; i++) {
206
+ int size = ivf.list_size(i);
207
+ const faiss::Index::idx_t *ids = ivf.get_ids (i);
208
+ const uint8_t *codes = ivf.get_codes (i);
209
+ for (int j = 0; j < size; j++) {
210
+ faiss::Index::idx_t id = ids[j];
211
+ const int * ar = (const int*)&codes[code_size * j];
212
+ EXPECT_EQ (ar[0], id);
213
+ EXPECT_EQ (ar[1], i);
214
+ EXPECT_EQ (list_nos[id], i);
215
+ ntot ++;
216
+ }
217
+ }
218
+ EXPECT_EQ (ntot, nadd);
219
+
220
+ };