faiss 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (226) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +103 -3
  4. data/ext/faiss/ext.cpp +99 -32
  5. data/ext/faiss/extconf.rb +12 -2
  6. data/lib/faiss/ext.bundle +0 -0
  7. data/lib/faiss/index.rb +3 -3
  8. data/lib/faiss/index_binary.rb +3 -3
  9. data/lib/faiss/kmeans.rb +1 -1
  10. data/lib/faiss/pca_matrix.rb +2 -2
  11. data/lib/faiss/product_quantizer.rb +3 -3
  12. data/lib/faiss/version.rb +1 -1
  13. data/vendor/faiss/AutoTune.cpp +719 -0
  14. data/vendor/faiss/AutoTune.h +212 -0
  15. data/vendor/faiss/Clustering.cpp +261 -0
  16. data/vendor/faiss/Clustering.h +101 -0
  17. data/vendor/faiss/IVFlib.cpp +339 -0
  18. data/vendor/faiss/IVFlib.h +132 -0
  19. data/vendor/faiss/Index.cpp +171 -0
  20. data/vendor/faiss/Index.h +261 -0
  21. data/vendor/faiss/Index2Layer.cpp +437 -0
  22. data/vendor/faiss/Index2Layer.h +85 -0
  23. data/vendor/faiss/IndexBinary.cpp +77 -0
  24. data/vendor/faiss/IndexBinary.h +163 -0
  25. data/vendor/faiss/IndexBinaryFlat.cpp +83 -0
  26. data/vendor/faiss/IndexBinaryFlat.h +54 -0
  27. data/vendor/faiss/IndexBinaryFromFloat.cpp +78 -0
  28. data/vendor/faiss/IndexBinaryFromFloat.h +52 -0
  29. data/vendor/faiss/IndexBinaryHNSW.cpp +325 -0
  30. data/vendor/faiss/IndexBinaryHNSW.h +56 -0
  31. data/vendor/faiss/IndexBinaryIVF.cpp +671 -0
  32. data/vendor/faiss/IndexBinaryIVF.h +211 -0
  33. data/vendor/faiss/IndexFlat.cpp +508 -0
  34. data/vendor/faiss/IndexFlat.h +175 -0
  35. data/vendor/faiss/IndexHNSW.cpp +1090 -0
  36. data/vendor/faiss/IndexHNSW.h +170 -0
  37. data/vendor/faiss/IndexIVF.cpp +909 -0
  38. data/vendor/faiss/IndexIVF.h +353 -0
  39. data/vendor/faiss/IndexIVFFlat.cpp +502 -0
  40. data/vendor/faiss/IndexIVFFlat.h +118 -0
  41. data/vendor/faiss/IndexIVFPQ.cpp +1207 -0
  42. data/vendor/faiss/IndexIVFPQ.h +161 -0
  43. data/vendor/faiss/IndexIVFPQR.cpp +219 -0
  44. data/vendor/faiss/IndexIVFPQR.h +65 -0
  45. data/vendor/faiss/IndexIVFSpectralHash.cpp +331 -0
  46. data/vendor/faiss/IndexIVFSpectralHash.h +75 -0
  47. data/vendor/faiss/IndexLSH.cpp +225 -0
  48. data/vendor/faiss/IndexLSH.h +87 -0
  49. data/vendor/faiss/IndexLattice.cpp +143 -0
  50. data/vendor/faiss/IndexLattice.h +68 -0
  51. data/vendor/faiss/IndexPQ.cpp +1188 -0
  52. data/vendor/faiss/IndexPQ.h +199 -0
  53. data/vendor/faiss/IndexPreTransform.cpp +288 -0
  54. data/vendor/faiss/IndexPreTransform.h +91 -0
  55. data/vendor/faiss/IndexReplicas.cpp +123 -0
  56. data/vendor/faiss/IndexReplicas.h +76 -0
  57. data/vendor/faiss/IndexScalarQuantizer.cpp +317 -0
  58. data/vendor/faiss/IndexScalarQuantizer.h +127 -0
  59. data/vendor/faiss/IndexShards.cpp +317 -0
  60. data/vendor/faiss/IndexShards.h +100 -0
  61. data/vendor/faiss/InvertedLists.cpp +623 -0
  62. data/vendor/faiss/InvertedLists.h +334 -0
  63. data/vendor/faiss/LICENSE +21 -0
  64. data/vendor/faiss/MatrixStats.cpp +252 -0
  65. data/vendor/faiss/MatrixStats.h +62 -0
  66. data/vendor/faiss/MetaIndexes.cpp +351 -0
  67. data/vendor/faiss/MetaIndexes.h +126 -0
  68. data/vendor/faiss/OnDiskInvertedLists.cpp +674 -0
  69. data/vendor/faiss/OnDiskInvertedLists.h +127 -0
  70. data/vendor/faiss/VectorTransform.cpp +1157 -0
  71. data/vendor/faiss/VectorTransform.h +322 -0
  72. data/vendor/faiss/c_api/AutoTune_c.cpp +83 -0
  73. data/vendor/faiss/c_api/AutoTune_c.h +64 -0
  74. data/vendor/faiss/c_api/Clustering_c.cpp +139 -0
  75. data/vendor/faiss/c_api/Clustering_c.h +117 -0
  76. data/vendor/faiss/c_api/IndexFlat_c.cpp +140 -0
  77. data/vendor/faiss/c_api/IndexFlat_c.h +115 -0
  78. data/vendor/faiss/c_api/IndexIVFFlat_c.cpp +64 -0
  79. data/vendor/faiss/c_api/IndexIVFFlat_c.h +58 -0
  80. data/vendor/faiss/c_api/IndexIVF_c.cpp +92 -0
  81. data/vendor/faiss/c_api/IndexIVF_c.h +135 -0
  82. data/vendor/faiss/c_api/IndexLSH_c.cpp +37 -0
  83. data/vendor/faiss/c_api/IndexLSH_c.h +40 -0
  84. data/vendor/faiss/c_api/IndexShards_c.cpp +44 -0
  85. data/vendor/faiss/c_api/IndexShards_c.h +42 -0
  86. data/vendor/faiss/c_api/Index_c.cpp +105 -0
  87. data/vendor/faiss/c_api/Index_c.h +183 -0
  88. data/vendor/faiss/c_api/MetaIndexes_c.cpp +49 -0
  89. data/vendor/faiss/c_api/MetaIndexes_c.h +49 -0
  90. data/vendor/faiss/c_api/clone_index_c.cpp +23 -0
  91. data/vendor/faiss/c_api/clone_index_c.h +32 -0
  92. data/vendor/faiss/c_api/error_c.h +42 -0
  93. data/vendor/faiss/c_api/error_impl.cpp +27 -0
  94. data/vendor/faiss/c_api/error_impl.h +16 -0
  95. data/vendor/faiss/c_api/faiss_c.h +58 -0
  96. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +96 -0
  97. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.h +56 -0
  98. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +52 -0
  99. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.h +68 -0
  100. data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +17 -0
  101. data/vendor/faiss/c_api/gpu/GpuIndex_c.h +30 -0
  102. data/vendor/faiss/c_api/gpu/GpuIndicesOptions_c.h +38 -0
  103. data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +86 -0
  104. data/vendor/faiss/c_api/gpu/GpuResources_c.h +66 -0
  105. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +54 -0
  106. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.h +53 -0
  107. data/vendor/faiss/c_api/gpu/macros_impl.h +42 -0
  108. data/vendor/faiss/c_api/impl/AuxIndexStructures_c.cpp +220 -0
  109. data/vendor/faiss/c_api/impl/AuxIndexStructures_c.h +149 -0
  110. data/vendor/faiss/c_api/index_factory_c.cpp +26 -0
  111. data/vendor/faiss/c_api/index_factory_c.h +30 -0
  112. data/vendor/faiss/c_api/index_io_c.cpp +42 -0
  113. data/vendor/faiss/c_api/index_io_c.h +50 -0
  114. data/vendor/faiss/c_api/macros_impl.h +110 -0
  115. data/vendor/faiss/clone_index.cpp +147 -0
  116. data/vendor/faiss/clone_index.h +38 -0
  117. data/vendor/faiss/demos/demo_imi_flat.cpp +151 -0
  118. data/vendor/faiss/demos/demo_imi_pq.cpp +199 -0
  119. data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +146 -0
  120. data/vendor/faiss/demos/demo_sift1M.cpp +252 -0
  121. data/vendor/faiss/gpu/GpuAutoTune.cpp +95 -0
  122. data/vendor/faiss/gpu/GpuAutoTune.h +27 -0
  123. data/vendor/faiss/gpu/GpuCloner.cpp +403 -0
  124. data/vendor/faiss/gpu/GpuCloner.h +82 -0
  125. data/vendor/faiss/gpu/GpuClonerOptions.cpp +28 -0
  126. data/vendor/faiss/gpu/GpuClonerOptions.h +53 -0
  127. data/vendor/faiss/gpu/GpuDistance.h +52 -0
  128. data/vendor/faiss/gpu/GpuFaissAssert.h +29 -0
  129. data/vendor/faiss/gpu/GpuIndex.h +148 -0
  130. data/vendor/faiss/gpu/GpuIndexBinaryFlat.h +89 -0
  131. data/vendor/faiss/gpu/GpuIndexFlat.h +190 -0
  132. data/vendor/faiss/gpu/GpuIndexIVF.h +89 -0
  133. data/vendor/faiss/gpu/GpuIndexIVFFlat.h +85 -0
  134. data/vendor/faiss/gpu/GpuIndexIVFPQ.h +143 -0
  135. data/vendor/faiss/gpu/GpuIndexIVFScalarQuantizer.h +100 -0
  136. data/vendor/faiss/gpu/GpuIndicesOptions.h +30 -0
  137. data/vendor/faiss/gpu/GpuResources.cpp +52 -0
  138. data/vendor/faiss/gpu/GpuResources.h +73 -0
  139. data/vendor/faiss/gpu/StandardGpuResources.cpp +295 -0
  140. data/vendor/faiss/gpu/StandardGpuResources.h +114 -0
  141. data/vendor/faiss/gpu/impl/RemapIndices.cpp +43 -0
  142. data/vendor/faiss/gpu/impl/RemapIndices.h +24 -0
  143. data/vendor/faiss/gpu/perf/IndexWrapper-inl.h +71 -0
  144. data/vendor/faiss/gpu/perf/IndexWrapper.h +39 -0
  145. data/vendor/faiss/gpu/perf/PerfClustering.cpp +115 -0
  146. data/vendor/faiss/gpu/perf/PerfIVFPQAdd.cpp +139 -0
  147. data/vendor/faiss/gpu/perf/WriteIndex.cpp +102 -0
  148. data/vendor/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +130 -0
  149. data/vendor/faiss/gpu/test/TestGpuIndexFlat.cpp +371 -0
  150. data/vendor/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +550 -0
  151. data/vendor/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +450 -0
  152. data/vendor/faiss/gpu/test/TestGpuMemoryException.cpp +84 -0
  153. data/vendor/faiss/gpu/test/TestUtils.cpp +315 -0
  154. data/vendor/faiss/gpu/test/TestUtils.h +93 -0
  155. data/vendor/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +159 -0
  156. data/vendor/faiss/gpu/utils/DeviceMemory.cpp +77 -0
  157. data/vendor/faiss/gpu/utils/DeviceMemory.h +71 -0
  158. data/vendor/faiss/gpu/utils/DeviceUtils.h +185 -0
  159. data/vendor/faiss/gpu/utils/MemorySpace.cpp +89 -0
  160. data/vendor/faiss/gpu/utils/MemorySpace.h +44 -0
  161. data/vendor/faiss/gpu/utils/StackDeviceMemory.cpp +239 -0
  162. data/vendor/faiss/gpu/utils/StackDeviceMemory.h +129 -0
  163. data/vendor/faiss/gpu/utils/StaticUtils.h +83 -0
  164. data/vendor/faiss/gpu/utils/Timer.cpp +60 -0
  165. data/vendor/faiss/gpu/utils/Timer.h +52 -0
  166. data/vendor/faiss/impl/AuxIndexStructures.cpp +305 -0
  167. data/vendor/faiss/impl/AuxIndexStructures.h +246 -0
  168. data/vendor/faiss/impl/FaissAssert.h +95 -0
  169. data/vendor/faiss/impl/FaissException.cpp +66 -0
  170. data/vendor/faiss/impl/FaissException.h +71 -0
  171. data/vendor/faiss/impl/HNSW.cpp +818 -0
  172. data/vendor/faiss/impl/HNSW.h +275 -0
  173. data/vendor/faiss/impl/PolysemousTraining.cpp +953 -0
  174. data/vendor/faiss/impl/PolysemousTraining.h +158 -0
  175. data/vendor/faiss/impl/ProductQuantizer.cpp +876 -0
  176. data/vendor/faiss/impl/ProductQuantizer.h +242 -0
  177. data/vendor/faiss/impl/ScalarQuantizer.cpp +1628 -0
  178. data/vendor/faiss/impl/ScalarQuantizer.h +120 -0
  179. data/vendor/faiss/impl/ThreadedIndex-inl.h +192 -0
  180. data/vendor/faiss/impl/ThreadedIndex.h +80 -0
  181. data/vendor/faiss/impl/index_read.cpp +793 -0
  182. data/vendor/faiss/impl/index_write.cpp +558 -0
  183. data/vendor/faiss/impl/io.cpp +142 -0
  184. data/vendor/faiss/impl/io.h +98 -0
  185. data/vendor/faiss/impl/lattice_Zn.cpp +712 -0
  186. data/vendor/faiss/impl/lattice_Zn.h +199 -0
  187. data/vendor/faiss/index_factory.cpp +392 -0
  188. data/vendor/faiss/index_factory.h +25 -0
  189. data/vendor/faiss/index_io.h +75 -0
  190. data/vendor/faiss/misc/test_blas.cpp +84 -0
  191. data/vendor/faiss/tests/test_binary_flat.cpp +64 -0
  192. data/vendor/faiss/tests/test_dealloc_invlists.cpp +183 -0
  193. data/vendor/faiss/tests/test_ivfpq_codec.cpp +67 -0
  194. data/vendor/faiss/tests/test_ivfpq_indexing.cpp +98 -0
  195. data/vendor/faiss/tests/test_lowlevel_ivf.cpp +566 -0
  196. data/vendor/faiss/tests/test_merge.cpp +258 -0
  197. data/vendor/faiss/tests/test_omp_threads.cpp +14 -0
  198. data/vendor/faiss/tests/test_ondisk_ivf.cpp +220 -0
  199. data/vendor/faiss/tests/test_pairs_decoding.cpp +189 -0
  200. data/vendor/faiss/tests/test_params_override.cpp +231 -0
  201. data/vendor/faiss/tests/test_pq_encoding.cpp +98 -0
  202. data/vendor/faiss/tests/test_sliding_ivf.cpp +240 -0
  203. data/vendor/faiss/tests/test_threaded_index.cpp +253 -0
  204. data/vendor/faiss/tests/test_transfer_invlists.cpp +159 -0
  205. data/vendor/faiss/tutorial/cpp/1-Flat.cpp +98 -0
  206. data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +81 -0
  207. data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +93 -0
  208. data/vendor/faiss/tutorial/cpp/4-GPU.cpp +119 -0
  209. data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +99 -0
  210. data/vendor/faiss/utils/Heap.cpp +122 -0
  211. data/vendor/faiss/utils/Heap.h +495 -0
  212. data/vendor/faiss/utils/WorkerThread.cpp +126 -0
  213. data/vendor/faiss/utils/WorkerThread.h +61 -0
  214. data/vendor/faiss/utils/distances.cpp +765 -0
  215. data/vendor/faiss/utils/distances.h +243 -0
  216. data/vendor/faiss/utils/distances_simd.cpp +809 -0
  217. data/vendor/faiss/utils/extra_distances.cpp +336 -0
  218. data/vendor/faiss/utils/extra_distances.h +54 -0
  219. data/vendor/faiss/utils/hamming-inl.h +472 -0
  220. data/vendor/faiss/utils/hamming.cpp +792 -0
  221. data/vendor/faiss/utils/hamming.h +220 -0
  222. data/vendor/faiss/utils/random.cpp +192 -0
  223. data/vendor/faiss/utils/random.h +60 -0
  224. data/vendor/faiss/utils/utils.cpp +783 -0
  225. data/vendor/faiss/utils/utils.h +181 -0
  226. metadata +216 -2
@@ -0,0 +1,78 @@
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
+ // -*- c++ -*-
9
+
10
+ #include <faiss/IndexBinaryFromFloat.h>
11
+
12
+ #include <memory>
13
+ #include <faiss/utils/utils.h>
14
+
15
+ namespace faiss {
16
+
17
+
18
+ IndexBinaryFromFloat::IndexBinaryFromFloat() {}
19
+
20
+ IndexBinaryFromFloat::IndexBinaryFromFloat(Index *index)
21
+ : IndexBinary(index->d),
22
+ index(index),
23
+ own_fields(false) {
24
+ is_trained = index->is_trained;
25
+ ntotal = index->ntotal;
26
+ }
27
+
28
+ IndexBinaryFromFloat::~IndexBinaryFromFloat() {
29
+ if (own_fields) {
30
+ delete index;
31
+ }
32
+ }
33
+
34
+ void IndexBinaryFromFloat::add(idx_t n, const uint8_t *x) {
35
+ constexpr idx_t bs = 32768;
36
+ std::unique_ptr<float[]> xf(new float[bs * d]);
37
+
38
+ for (idx_t b = 0; b < n; b += bs) {
39
+ idx_t bn = std::min(bs, n - b);
40
+ binary_to_real(bn * d, x + b * code_size, xf.get());
41
+
42
+ index->add(bn, xf.get());
43
+ }
44
+ ntotal = index->ntotal;
45
+ }
46
+
47
+ void IndexBinaryFromFloat::reset() {
48
+ index->reset();
49
+ ntotal = index->ntotal;
50
+ }
51
+
52
+ void IndexBinaryFromFloat::search(idx_t n, const uint8_t *x, idx_t k,
53
+ int32_t *distances, idx_t *labels) const {
54
+ constexpr idx_t bs = 32768;
55
+ std::unique_ptr<float[]> xf(new float[bs * d]);
56
+ std::unique_ptr<float[]> df(new float[bs * k]);
57
+
58
+ for (idx_t b = 0; b < n; b += bs) {
59
+ idx_t bn = std::min(bs, n - b);
60
+ binary_to_real(bn * d, x + b * code_size, xf.get());
61
+
62
+ index->search(bn, xf.get(), k, df.get(), labels + b * k);
63
+ for (int i = 0; i < bn * k; ++i) {
64
+ distances[b * k + i] = int32_t(std::round(df[i] / 4.0));
65
+ }
66
+ }
67
+ }
68
+
69
+ void IndexBinaryFromFloat::train(idx_t n, const uint8_t *x) {
70
+ std::unique_ptr<float[]> xf(new float[n * d]);
71
+ binary_to_real(n * d, x, xf.get());
72
+
73
+ index->train(n, xf.get());
74
+ is_trained = true;
75
+ ntotal = index->ntotal;
76
+ }
77
+
78
+ } // namespace faiss
@@ -0,0 +1,52 @@
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
+ // -*- c++ -*-
9
+
10
+ #ifndef FAISS_INDEX_BINARY_FROM_FLOAT_H
11
+ #define FAISS_INDEX_BINARY_FROM_FLOAT_H
12
+
13
+ #include <faiss/IndexBinary.h>
14
+
15
+
16
+ namespace faiss {
17
+
18
+
19
+ struct Index;
20
+
21
+ /** IndexBinary backed by a float Index.
22
+ *
23
+ * Supports adding vertices and searching them.
24
+ *
25
+ * All queries are symmetric because there is no distinction between codes and
26
+ * vectors.
27
+ */
28
+ struct IndexBinaryFromFloat : IndexBinary {
29
+ Index *index = nullptr;
30
+
31
+ bool own_fields = false; ///< Whether object owns the index pointer.
32
+
33
+ IndexBinaryFromFloat();
34
+
35
+ explicit IndexBinaryFromFloat(Index *index);
36
+
37
+ ~IndexBinaryFromFloat();
38
+
39
+ void add(idx_t n, const uint8_t *x) override;
40
+
41
+ void reset() override;
42
+
43
+ void search(idx_t n, const uint8_t *x, idx_t k,
44
+ int32_t *distances, idx_t *labels) const override;
45
+
46
+ void train(idx_t n, const uint8_t *x) override;
47
+ };
48
+
49
+
50
+ } // namespace faiss
51
+
52
+ #endif // FAISS_INDEX_BINARY_FROM_FLOAT_H
@@ -0,0 +1,325 @@
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
+ // -*- c++ -*-
9
+
10
+ #include <faiss/IndexBinaryHNSW.h>
11
+
12
+
13
+ #include <memory>
14
+ #include <cstdlib>
15
+ #include <cassert>
16
+ #include <cstring>
17
+ #include <cstdio>
18
+ #include <cmath>
19
+ #include <omp.h>
20
+
21
+ #include <unordered_set>
22
+ #include <queue>
23
+
24
+ #include <sys/types.h>
25
+ #include <sys/stat.h>
26
+ #include <unistd.h>
27
+ #include <stdint.h>
28
+
29
+ #include <faiss/utils/random.h>
30
+ #include <faiss/utils/Heap.h>
31
+ #include <faiss/impl/FaissAssert.h>
32
+ #include <faiss/IndexBinaryFlat.h>
33
+ #include <faiss/utils/hamming.h>
34
+ #include <faiss/impl/AuxIndexStructures.h>
35
+
36
+ namespace faiss {
37
+
38
+
39
+ /**************************************************************
40
+ * add / search blocks of descriptors
41
+ **************************************************************/
42
+
43
+ namespace {
44
+
45
+
46
+ void hnsw_add_vertices(IndexBinaryHNSW& index_hnsw,
47
+ size_t n0,
48
+ size_t n, const uint8_t *x,
49
+ bool verbose,
50
+ bool preset_levels = false) {
51
+ HNSW& hnsw = index_hnsw.hnsw;
52
+ size_t ntotal = n0 + n;
53
+ double t0 = getmillisecs();
54
+ if (verbose) {
55
+ printf("hnsw_add_vertices: adding %ld elements on top of %ld "
56
+ "(preset_levels=%d)\n",
57
+ n, n0, int(preset_levels));
58
+ }
59
+
60
+ int max_level = hnsw.prepare_level_tab(n, preset_levels);
61
+
62
+ if (verbose) {
63
+ printf(" max_level = %d\n", max_level);
64
+ }
65
+
66
+ std::vector<omp_lock_t> locks(ntotal);
67
+ for(int i = 0; i < ntotal; i++) {
68
+ omp_init_lock(&locks[i]);
69
+ }
70
+
71
+ // add vectors from highest to lowest level
72
+ std::vector<int> hist;
73
+ std::vector<int> order(n);
74
+
75
+ { // make buckets with vectors of the same level
76
+
77
+ // build histogram
78
+ for (int i = 0; i < n; i++) {
79
+ HNSW::storage_idx_t pt_id = i + n0;
80
+ int pt_level = hnsw.levels[pt_id] - 1;
81
+ while (pt_level >= hist.size()) {
82
+ hist.push_back(0);
83
+ }
84
+ hist[pt_level] ++;
85
+ }
86
+
87
+ // accumulate
88
+ std::vector<int> offsets(hist.size() + 1, 0);
89
+ for (int i = 0; i < hist.size() - 1; i++) {
90
+ offsets[i + 1] = offsets[i] + hist[i];
91
+ }
92
+
93
+ // bucket sort
94
+ for (int i = 0; i < n; i++) {
95
+ HNSW::storage_idx_t pt_id = i + n0;
96
+ int pt_level = hnsw.levels[pt_id] - 1;
97
+ order[offsets[pt_level]++] = pt_id;
98
+ }
99
+ }
100
+
101
+ { // perform add
102
+ RandomGenerator rng2(789);
103
+
104
+ int i1 = n;
105
+
106
+ for (int pt_level = hist.size() - 1; pt_level >= 0; pt_level--) {
107
+ int i0 = i1 - hist[pt_level];
108
+
109
+ if (verbose) {
110
+ printf("Adding %d elements at level %d\n",
111
+ i1 - i0, pt_level);
112
+ }
113
+
114
+ // random permutation to get rid of dataset order bias
115
+ for (int j = i0; j < i1; j++) {
116
+ std::swap(order[j], order[j + rng2.rand_int(i1 - j)]);
117
+ }
118
+
119
+ #pragma omp parallel
120
+ {
121
+ VisitedTable vt (ntotal);
122
+
123
+ std::unique_ptr<DistanceComputer> dis(
124
+ index_hnsw.get_distance_computer()
125
+ );
126
+ int prev_display = verbose && omp_get_thread_num() == 0 ? 0 : -1;
127
+
128
+ #pragma omp for schedule(dynamic)
129
+ for (int i = i0; i < i1; i++) {
130
+ HNSW::storage_idx_t pt_id = order[i];
131
+ dis->set_query((float *)(x + (pt_id - n0) * index_hnsw.code_size));
132
+
133
+ hnsw.add_with_locks(*dis, pt_level, pt_id, locks, vt);
134
+
135
+ if (prev_display >= 0 && i - i0 > prev_display + 10000) {
136
+ prev_display = i - i0;
137
+ printf(" %d / %d\r", i - i0, i1 - i0);
138
+ fflush(stdout);
139
+ }
140
+ }
141
+ }
142
+ i1 = i0;
143
+ }
144
+ FAISS_ASSERT(i1 == 0);
145
+ }
146
+ if (verbose) {
147
+ printf("Done in %.3f ms\n", getmillisecs() - t0);
148
+ }
149
+
150
+ for(int i = 0; i < ntotal; i++)
151
+ omp_destroy_lock(&locks[i]);
152
+ }
153
+
154
+
155
+ } // anonymous namespace
156
+
157
+
158
+ /**************************************************************
159
+ * IndexBinaryHNSW implementation
160
+ **************************************************************/
161
+
162
+ IndexBinaryHNSW::IndexBinaryHNSW()
163
+ {
164
+ is_trained = true;
165
+ }
166
+
167
+ IndexBinaryHNSW::IndexBinaryHNSW(int d, int M)
168
+ : IndexBinary(d),
169
+ hnsw(M),
170
+ own_fields(true),
171
+ storage(new IndexBinaryFlat(d))
172
+ {
173
+ is_trained = true;
174
+ }
175
+
176
+ IndexBinaryHNSW::IndexBinaryHNSW(IndexBinary *storage, int M)
177
+ : IndexBinary(storage->d),
178
+ hnsw(M),
179
+ own_fields(false),
180
+ storage(storage)
181
+ {
182
+ is_trained = true;
183
+ }
184
+
185
+ IndexBinaryHNSW::~IndexBinaryHNSW() {
186
+ if (own_fields) {
187
+ delete storage;
188
+ }
189
+ }
190
+
191
+ void IndexBinaryHNSW::train(idx_t n, const uint8_t *x)
192
+ {
193
+ // hnsw structure does not require training
194
+ storage->train(n, x);
195
+ is_trained = true;
196
+ }
197
+
198
+ void IndexBinaryHNSW::search(idx_t n, const uint8_t *x, idx_t k,
199
+ int32_t *distances, idx_t *labels) const
200
+ {
201
+ #pragma omp parallel
202
+ {
203
+ VisitedTable vt(ntotal);
204
+ std::unique_ptr<DistanceComputer> dis(get_distance_computer());
205
+
206
+ #pragma omp for
207
+ for(idx_t i = 0; i < n; i++) {
208
+ idx_t *idxi = labels + i * k;
209
+ float *simi = (float *)(distances + i * k);
210
+
211
+ dis->set_query((float *)(x + i * code_size));
212
+
213
+ maxheap_heapify(k, simi, idxi);
214
+ hnsw.search(*dis, k, idxi, simi, vt);
215
+ maxheap_reorder(k, simi, idxi);
216
+ }
217
+ }
218
+
219
+ #pragma omp parallel for
220
+ for (int i = 0; i < n * k; ++i) {
221
+ distances[i] = std::round(((float *)distances)[i]);
222
+ }
223
+ }
224
+
225
+
226
+ void IndexBinaryHNSW::add(idx_t n, const uint8_t *x)
227
+ {
228
+ FAISS_THROW_IF_NOT(is_trained);
229
+ int n0 = ntotal;
230
+ storage->add(n, x);
231
+ ntotal = storage->ntotal;
232
+
233
+ hnsw_add_vertices(*this, n0, n, x, verbose,
234
+ hnsw.levels.size() == ntotal);
235
+ }
236
+
237
+ void IndexBinaryHNSW::reset()
238
+ {
239
+ hnsw.reset();
240
+ storage->reset();
241
+ ntotal = 0;
242
+ }
243
+
244
+ void IndexBinaryHNSW::reconstruct(idx_t key, uint8_t *recons) const
245
+ {
246
+ storage->reconstruct(key, recons);
247
+ }
248
+
249
+
250
+ namespace {
251
+
252
+
253
+ template<class HammingComputer>
254
+ struct FlatHammingDis : DistanceComputer {
255
+ const int code_size;
256
+ const uint8_t *b;
257
+ size_t ndis;
258
+ HammingComputer hc;
259
+
260
+ float operator () (idx_t i) override {
261
+ ndis++;
262
+ return hc.hamming(b + i * code_size);
263
+ }
264
+
265
+ float symmetric_dis(idx_t i, idx_t j) override {
266
+ return HammingComputerDefault(b + j * code_size, code_size)
267
+ .hamming(b + i * code_size);
268
+ }
269
+
270
+
271
+ explicit FlatHammingDis(const IndexBinaryFlat& storage)
272
+ : code_size(storage.code_size),
273
+ b(storage.xb.data()),
274
+ ndis(0),
275
+ hc() {}
276
+
277
+ // NOTE: Pointers are cast from float in order to reuse the floating-point
278
+ // DistanceComputer.
279
+ void set_query(const float *x) override {
280
+ hc.set((uint8_t *)x, code_size);
281
+ }
282
+
283
+ ~FlatHammingDis() override {
284
+ #pragma omp critical
285
+ {
286
+ hnsw_stats.ndis += ndis;
287
+ }
288
+ }
289
+ };
290
+
291
+
292
+ } // namespace
293
+
294
+
295
+ DistanceComputer *IndexBinaryHNSW::get_distance_computer() const {
296
+ IndexBinaryFlat *flat_storage = dynamic_cast<IndexBinaryFlat *>(storage);
297
+
298
+ FAISS_ASSERT(flat_storage != nullptr);
299
+
300
+ switch(code_size) {
301
+ case 4:
302
+ return new FlatHammingDis<HammingComputer4>(*flat_storage);
303
+ case 8:
304
+ return new FlatHammingDis<HammingComputer8>(*flat_storage);
305
+ case 16:
306
+ return new FlatHammingDis<HammingComputer16>(*flat_storage);
307
+ case 20:
308
+ return new FlatHammingDis<HammingComputer20>(*flat_storage);
309
+ case 32:
310
+ return new FlatHammingDis<HammingComputer32>(*flat_storage);
311
+ case 64:
312
+ return new FlatHammingDis<HammingComputer64>(*flat_storage);
313
+ default:
314
+ if (code_size % 8 == 0) {
315
+ return new FlatHammingDis<HammingComputerM8>(*flat_storage);
316
+ } else if (code_size % 4 == 0) {
317
+ return new FlatHammingDis<HammingComputerM4>(*flat_storage);
318
+ }
319
+ }
320
+
321
+ return new FlatHammingDis<HammingComputerDefault>(*flat_storage);
322
+ }
323
+
324
+
325
+ } // namespace faiss