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,60 @@
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/gpu/utils/Timer.h>
10
+ #include <faiss/gpu/utils/DeviceUtils.h>
11
+ #include <faiss/impl/FaissAssert.h>
12
+
13
+ namespace faiss { namespace gpu {
14
+
15
+ KernelTimer::KernelTimer(cudaStream_t stream)
16
+ : startEvent_(0),
17
+ stopEvent_(0),
18
+ stream_(stream),
19
+ valid_(true) {
20
+ CUDA_VERIFY(cudaEventCreate(&startEvent_));
21
+ CUDA_VERIFY(cudaEventCreate(&stopEvent_));
22
+
23
+ CUDA_VERIFY(cudaEventRecord(startEvent_, stream_));
24
+ }
25
+
26
+ KernelTimer::~KernelTimer() {
27
+ CUDA_VERIFY(cudaEventDestroy(startEvent_));
28
+ CUDA_VERIFY(cudaEventDestroy(stopEvent_));
29
+ }
30
+
31
+ float
32
+ KernelTimer::elapsedMilliseconds() {
33
+ FAISS_ASSERT(valid_);
34
+
35
+ CUDA_VERIFY(cudaEventRecord(stopEvent_, stream_));
36
+ CUDA_VERIFY(cudaEventSynchronize(stopEvent_));
37
+
38
+ auto time = 0.0f;
39
+ CUDA_VERIFY(cudaEventElapsedTime(&time, startEvent_, stopEvent_));
40
+ valid_ = false;
41
+
42
+ return time;
43
+ }
44
+
45
+ CpuTimer::CpuTimer() {
46
+ clock_gettime(CLOCK_REALTIME, &start_);
47
+ }
48
+
49
+ float
50
+ CpuTimer::elapsedMilliseconds() {
51
+ struct timespec end;
52
+ clock_gettime(CLOCK_REALTIME, &end);
53
+
54
+ auto diffS = end.tv_sec - start_.tv_sec;
55
+ auto diffNs = end.tv_nsec - start_.tv_nsec;
56
+
57
+ return 1000.0f * (float) diffS + ((float) diffNs) / 1000000.0f;
58
+ }
59
+
60
+ } } // namespace
@@ -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
+
9
+ #pragma once
10
+
11
+ #include <cuda_runtime.h>
12
+ #include <time.h>
13
+
14
+ namespace faiss { namespace gpu {
15
+
16
+ /// Utility class for timing execution of a kernel
17
+ class KernelTimer {
18
+ public:
19
+ /// Constructor starts the timer and adds an event into the current
20
+ /// device stream
21
+ KernelTimer(cudaStream_t stream = 0);
22
+
23
+ /// Destructor releases event resources
24
+ ~KernelTimer();
25
+
26
+ /// Adds a stop event then synchronizes on the stop event to get the
27
+ /// actual GPU-side kernel timings for any kernels launched in the
28
+ /// current stream. Returns the number of milliseconds elapsed.
29
+ /// Can only be called once.
30
+ float elapsedMilliseconds();
31
+
32
+ private:
33
+ cudaEvent_t startEvent_;
34
+ cudaEvent_t stopEvent_;
35
+ cudaStream_t stream_;
36
+ bool valid_;
37
+ };
38
+
39
+ /// CPU wallclock elapsed timer
40
+ class CpuTimer {
41
+ public:
42
+ /// Creates and starts a new timer
43
+ CpuTimer();
44
+
45
+ /// Returns elapsed time in milliseconds
46
+ float elapsedMilliseconds();
47
+
48
+ private:
49
+ struct timespec start_;
50
+ };
51
+
52
+ } } // namespace
@@ -0,0 +1,305 @@
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 <cstring>
11
+
12
+ #include <faiss/impl/AuxIndexStructures.h>
13
+
14
+ #include <faiss/impl/FaissAssert.h>
15
+
16
+
17
+ namespace faiss {
18
+
19
+
20
+ /***********************************************************************
21
+ * RangeSearchResult
22
+ ***********************************************************************/
23
+
24
+ RangeSearchResult::RangeSearchResult (idx_t nq, bool alloc_lims): nq (nq) {
25
+ if (alloc_lims) {
26
+ lims = new size_t [nq + 1];
27
+ memset (lims, 0, sizeof(*lims) * (nq + 1));
28
+ } else {
29
+ lims = nullptr;
30
+ }
31
+ labels = nullptr;
32
+ distances = nullptr;
33
+ buffer_size = 1024 * 256;
34
+ }
35
+
36
+ /// called when lims contains the nb of elements result entries
37
+ /// for each query
38
+ void RangeSearchResult::do_allocation () {
39
+ size_t ofs = 0;
40
+ for (int i = 0; i < nq; i++) {
41
+ size_t n = lims[i];
42
+ lims [i] = ofs;
43
+ ofs += n;
44
+ }
45
+ lims [nq] = ofs;
46
+ labels = new idx_t [ofs];
47
+ distances = new float [ofs];
48
+ }
49
+
50
+ RangeSearchResult::~RangeSearchResult () {
51
+ delete [] labels;
52
+ delete [] distances;
53
+ delete [] lims;
54
+ }
55
+
56
+
57
+
58
+
59
+
60
+ /***********************************************************************
61
+ * BufferList
62
+ ***********************************************************************/
63
+
64
+
65
+ BufferList::BufferList (size_t buffer_size):
66
+ buffer_size (buffer_size)
67
+ {
68
+ wp = buffer_size;
69
+ }
70
+
71
+ BufferList::~BufferList ()
72
+ {
73
+ for (int i = 0; i < buffers.size(); i++) {
74
+ delete [] buffers[i].ids;
75
+ delete [] buffers[i].dis;
76
+ }
77
+ }
78
+
79
+ void BufferList::add (idx_t id, float dis) {
80
+ if (wp == buffer_size) { // need new buffer
81
+ append_buffer();
82
+ }
83
+ Buffer & buf = buffers.back();
84
+ buf.ids [wp] = id;
85
+ buf.dis [wp] = dis;
86
+ wp++;
87
+ }
88
+
89
+
90
+ void BufferList::append_buffer ()
91
+ {
92
+ Buffer buf = {new idx_t [buffer_size], new float [buffer_size]};
93
+ buffers.push_back (buf);
94
+ wp = 0;
95
+ }
96
+
97
+ /// copy elemnts ofs:ofs+n-1 seen as linear data in the buffers to
98
+ /// tables dest_ids, dest_dis
99
+ void BufferList::copy_range (size_t ofs, size_t n,
100
+ idx_t * dest_ids, float *dest_dis)
101
+ {
102
+ size_t bno = ofs / buffer_size;
103
+ ofs -= bno * buffer_size;
104
+ while (n > 0) {
105
+ size_t ncopy = ofs + n < buffer_size ? n : buffer_size - ofs;
106
+ Buffer buf = buffers [bno];
107
+ memcpy (dest_ids, buf.ids + ofs, ncopy * sizeof(*dest_ids));
108
+ memcpy (dest_dis, buf.dis + ofs, ncopy * sizeof(*dest_dis));
109
+ dest_ids += ncopy;
110
+ dest_dis += ncopy;
111
+ ofs = 0;
112
+ bno ++;
113
+ n -= ncopy;
114
+ }
115
+ }
116
+
117
+
118
+ /***********************************************************************
119
+ * RangeSearchPartialResult
120
+ ***********************************************************************/
121
+
122
+ void RangeQueryResult::add (float dis, idx_t id) {
123
+ nres++;
124
+ pres->add (id, dis);
125
+ }
126
+
127
+
128
+
129
+ RangeSearchPartialResult::RangeSearchPartialResult (RangeSearchResult * res_in):
130
+ BufferList(res_in->buffer_size),
131
+ res(res_in)
132
+ {}
133
+
134
+
135
+ /// begin a new result
136
+ RangeQueryResult &
137
+ RangeSearchPartialResult::new_result (idx_t qno)
138
+ {
139
+ RangeQueryResult qres = {qno, 0, this};
140
+ queries.push_back (qres);
141
+ return queries.back();
142
+ }
143
+
144
+
145
+ void RangeSearchPartialResult::finalize ()
146
+ {
147
+ set_lims ();
148
+ #pragma omp barrier
149
+
150
+ #pragma omp single
151
+ res->do_allocation ();
152
+
153
+ #pragma omp barrier
154
+ copy_result ();
155
+ }
156
+
157
+
158
+ /// called by range_search before do_allocation
159
+ void RangeSearchPartialResult::set_lims ()
160
+ {
161
+ for (int i = 0; i < queries.size(); i++) {
162
+ RangeQueryResult & qres = queries[i];
163
+ res->lims[qres.qno] = qres.nres;
164
+ }
165
+ }
166
+
167
+ /// called by range_search after do_allocation
168
+ void RangeSearchPartialResult::copy_result (bool incremental)
169
+ {
170
+ size_t ofs = 0;
171
+ for (int i = 0; i < queries.size(); i++) {
172
+ RangeQueryResult & qres = queries[i];
173
+
174
+ copy_range (ofs, qres.nres,
175
+ res->labels + res->lims[qres.qno],
176
+ res->distances + res->lims[qres.qno]);
177
+ if (incremental) {
178
+ res->lims[qres.qno] += qres.nres;
179
+ }
180
+ ofs += qres.nres;
181
+ }
182
+ }
183
+
184
+ void RangeSearchPartialResult::merge (std::vector <RangeSearchPartialResult *> &
185
+ partial_results, bool do_delete)
186
+ {
187
+
188
+ int npres = partial_results.size();
189
+ if (npres == 0) return;
190
+ RangeSearchResult *result = partial_results[0]->res;
191
+ size_t nx = result->nq;
192
+
193
+ // count
194
+ for (const RangeSearchPartialResult * pres : partial_results) {
195
+ if (!pres) continue;
196
+ for (const RangeQueryResult &qres : pres->queries) {
197
+ result->lims[qres.qno] += qres.nres;
198
+ }
199
+ }
200
+ result->do_allocation ();
201
+ for (int j = 0; j < npres; j++) {
202
+ if (!partial_results[j]) continue;
203
+ partial_results[j]->copy_result (true);
204
+ if (do_delete) {
205
+ delete partial_results[j];
206
+ partial_results[j] = nullptr;
207
+ }
208
+ }
209
+
210
+ // reset the limits
211
+ for (size_t i = nx; i > 0; i--) {
212
+ result->lims [i] = result->lims [i - 1];
213
+ }
214
+ result->lims [0] = 0;
215
+ }
216
+
217
+ /***********************************************************************
218
+ * IDSelectorRange
219
+ ***********************************************************************/
220
+
221
+ IDSelectorRange::IDSelectorRange (idx_t imin, idx_t imax):
222
+ imin (imin), imax (imax)
223
+ {
224
+ }
225
+
226
+ bool IDSelectorRange::is_member (idx_t id) const
227
+ {
228
+ return id >= imin && id < imax;
229
+ }
230
+
231
+
232
+ /***********************************************************************
233
+ * IDSelectorBatch
234
+ ***********************************************************************/
235
+
236
+ IDSelectorBatch::IDSelectorBatch (size_t n, const idx_t *indices)
237
+ {
238
+ nbits = 0;
239
+ while (n > (1L << nbits)) nbits++;
240
+ nbits += 5;
241
+ // for n = 1M, nbits = 25 is optimal, see P56659518
242
+
243
+ mask = (1L << nbits) - 1;
244
+ bloom.resize (1UL << (nbits - 3), 0);
245
+ for (long i = 0; i < n; i++) {
246
+ Index::idx_t id = indices[i];
247
+ set.insert(id);
248
+ id &= mask;
249
+ bloom[id >> 3] |= 1 << (id & 7);
250
+ }
251
+ }
252
+
253
+ bool IDSelectorBatch::is_member (idx_t i) const
254
+ {
255
+ long im = i & mask;
256
+ if(!(bloom[im>>3] & (1 << (im & 7)))) {
257
+ return 0;
258
+ }
259
+ return set.count(i);
260
+ }
261
+
262
+
263
+ /***********************************************************
264
+ * Interrupt callback
265
+ ***********************************************************/
266
+
267
+
268
+ std::unique_ptr<InterruptCallback> InterruptCallback::instance;
269
+
270
+ std::mutex InterruptCallback::lock;
271
+
272
+ void InterruptCallback::clear_instance () {
273
+ delete instance.release ();
274
+ }
275
+
276
+ void InterruptCallback::check () {
277
+ if (!instance.get()) {
278
+ return;
279
+ }
280
+ if (instance->want_interrupt ()) {
281
+ FAISS_THROW_MSG ("computation interrupted");
282
+ }
283
+ }
284
+
285
+ bool InterruptCallback::is_interrupted () {
286
+ if (!instance.get()) {
287
+ return false;
288
+ }
289
+ std::lock_guard<std::mutex> guard(lock);
290
+ return instance->want_interrupt();
291
+ }
292
+
293
+
294
+ size_t InterruptCallback::get_period_hint (size_t flops) {
295
+ if (!instance.get()) {
296
+ return 1L << 30; // never check
297
+ }
298
+ // for 10M flops, it is reasonable to check once every 10 iterations
299
+ return std::max((size_t)10 * 10 * 1000 * 1000 / (flops + 1), (size_t)1);
300
+ }
301
+
302
+
303
+
304
+
305
+ } // namespace faiss
@@ -0,0 +1,246 @@
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
+ // Auxiliary index structures, that are used in indexes but that can
11
+ // be forward-declared
12
+
13
+ #ifndef FAISS_AUX_INDEX_STRUCTURES_H
14
+ #define FAISS_AUX_INDEX_STRUCTURES_H
15
+
16
+ #include <stdint.h>
17
+
18
+ #include <vector>
19
+ #include <unordered_set>
20
+ #include <memory>
21
+ #include <mutex>
22
+
23
+ #include <faiss/Index.h>
24
+
25
+ namespace faiss {
26
+
27
+ /** The objective is to have a simple result structure while
28
+ * minimizing the number of mem copies in the result. The method
29
+ * do_allocation can be overloaded to allocate the result tables in
30
+ * the matrix type of a scripting language like Lua or Python. */
31
+ struct RangeSearchResult {
32
+ size_t nq; ///< nb of queries
33
+ size_t *lims; ///< size (nq + 1)
34
+
35
+ typedef Index::idx_t idx_t;
36
+
37
+ idx_t *labels; ///< result for query i is labels[lims[i]:lims[i+1]]
38
+ float *distances; ///< corresponding distances (not sorted)
39
+
40
+ size_t buffer_size; ///< size of the result buffers used
41
+
42
+ /// lims must be allocated on input to range_search.
43
+ explicit RangeSearchResult (idx_t nq, bool alloc_lims=true);
44
+
45
+ /// called when lims contains the nb of elements result entries
46
+ /// for each query
47
+
48
+ virtual void do_allocation ();
49
+
50
+ virtual ~RangeSearchResult ();
51
+ };
52
+
53
+
54
+ /**
55
+
56
+ Encapsulates a set of ids to remove. */
57
+ struct IDSelector {
58
+ typedef Index::idx_t idx_t;
59
+ virtual bool is_member (idx_t id) const = 0;
60
+ virtual ~IDSelector() {}
61
+ };
62
+
63
+
64
+
65
+ /** remove ids between [imni, imax) */
66
+ struct IDSelectorRange: IDSelector {
67
+ idx_t imin, imax;
68
+
69
+ IDSelectorRange (idx_t imin, idx_t imax);
70
+ bool is_member(idx_t id) const override;
71
+ ~IDSelectorRange() override {}
72
+ };
73
+
74
+
75
+ /** Remove ids from a set. Repetitions of ids in the indices set
76
+ * passed to the constructor does not hurt performance. The hash
77
+ * function used for the bloom filter and GCC's implementation of
78
+ * unordered_set are just the least significant bits of the id. This
79
+ * works fine for random ids or ids in sequences but will produce many
80
+ * hash collisions if lsb's are always the same */
81
+ struct IDSelectorBatch: IDSelector {
82
+
83
+ std::unordered_set<idx_t> set;
84
+
85
+ typedef unsigned char uint8_t;
86
+ std::vector<uint8_t> bloom; // assumes low bits of id are a good hash value
87
+ int nbits;
88
+ idx_t mask;
89
+
90
+ IDSelectorBatch (size_t n, const idx_t *indices);
91
+ bool is_member(idx_t id) const override;
92
+ ~IDSelectorBatch() override {}
93
+ };
94
+
95
+ /****************************************************************
96
+ * Result structures for range search.
97
+ *
98
+ * The main constraint here is that we want to support parallel
99
+ * queries from different threads in various ways: 1 thread per query,
100
+ * several threads per query. We store the actual results in blocks of
101
+ * fixed size rather than exponentially increasing memory. At the end,
102
+ * we copy the block content to a linear result array.
103
+ *****************************************************************/
104
+
105
+ /** List of temporary buffers used to store results before they are
106
+ * copied to the RangeSearchResult object. */
107
+ struct BufferList {
108
+ typedef Index::idx_t idx_t;
109
+
110
+ // buffer sizes in # entries
111
+ size_t buffer_size;
112
+
113
+ struct Buffer {
114
+ idx_t *ids;
115
+ float *dis;
116
+ };
117
+
118
+ std::vector<Buffer> buffers;
119
+ size_t wp; ///< write pointer in the last buffer.
120
+
121
+ explicit BufferList (size_t buffer_size);
122
+
123
+ ~BufferList ();
124
+
125
+ /// create a new buffer
126
+ void append_buffer ();
127
+
128
+ /// add one result, possibly appending a new buffer if needed
129
+ void add (idx_t id, float dis);
130
+
131
+ /// copy elemnts ofs:ofs+n-1 seen as linear data in the buffers to
132
+ /// tables dest_ids, dest_dis
133
+ void copy_range (size_t ofs, size_t n,
134
+ idx_t * dest_ids, float *dest_dis);
135
+
136
+ };
137
+
138
+ struct RangeSearchPartialResult;
139
+
140
+ /// result structure for a single query
141
+ struct RangeQueryResult {
142
+ using idx_t = Index::idx_t;
143
+ idx_t qno; //< id of the query
144
+ size_t nres; //< nb of results for this query
145
+ RangeSearchPartialResult * pres;
146
+
147
+ /// called by search function to report a new result
148
+ void add (float dis, idx_t id);
149
+ };
150
+
151
+ /// the entries in the buffers are split per query
152
+ struct RangeSearchPartialResult: BufferList {
153
+ RangeSearchResult * res;
154
+
155
+ /// eventually the result will be stored in res_in
156
+ explicit RangeSearchPartialResult (RangeSearchResult * res_in);
157
+
158
+ /// query ids + nb of results per query.
159
+ std::vector<RangeQueryResult> queries;
160
+
161
+ /// begin a new result
162
+ RangeQueryResult & new_result (idx_t qno);
163
+
164
+ /*****************************************
165
+ * functions used at the end of the search to merge the result
166
+ * lists */
167
+ void finalize ();
168
+
169
+ /// called by range_search before do_allocation
170
+ void set_lims ();
171
+
172
+ /// called by range_search after do_allocation
173
+ void copy_result (bool incremental = false);
174
+
175
+ /// merge a set of PartialResult's into one RangeSearchResult
176
+ /// on ouptut the partialresults are empty!
177
+ static void merge (std::vector <RangeSearchPartialResult *> &
178
+ partial_results, bool do_delete=true);
179
+
180
+ };
181
+
182
+
183
+ /***********************************************************
184
+ * The distance computer maintains a current query and computes
185
+ * distances to elements in an index that supports random access.
186
+ *
187
+ * The DistanceComputer is not intended to be thread-safe (eg. because
188
+ * it maintains counters) so the distance functions are not const,
189
+ * instanciate one from each thread if needed.
190
+ ***********************************************************/
191
+ struct DistanceComputer {
192
+ using idx_t = Index::idx_t;
193
+
194
+ /// called before computing distances
195
+ virtual void set_query(const float *x) = 0;
196
+
197
+ /// compute distance of vector i to current query
198
+ virtual float operator () (idx_t i) = 0;
199
+
200
+ /// compute distance between two stored vectors
201
+ virtual float symmetric_dis (idx_t i, idx_t j) = 0;
202
+
203
+ virtual ~DistanceComputer() {}
204
+ };
205
+
206
+ /***********************************************************
207
+ * Interrupt callback
208
+ ***********************************************************/
209
+
210
+ struct InterruptCallback {
211
+ virtual bool want_interrupt () = 0;
212
+ virtual ~InterruptCallback() {}
213
+
214
+ // lock that protects concurrent calls to is_interrupted
215
+ static std::mutex lock;
216
+
217
+ static std::unique_ptr<InterruptCallback> instance;
218
+
219
+ static void clear_instance ();
220
+
221
+ /** check if:
222
+ * - an interrupt callback is set
223
+ * - the callback retuns true
224
+ * if this is the case, then throw an exception. Should not be called
225
+ * from multiple threds.
226
+ */
227
+ static void check ();
228
+
229
+ /// same as check() but return true if is interrupted instead of
230
+ /// throwing. Can be called from multiple threads.
231
+ static bool is_interrupted ();
232
+
233
+ /** assuming each iteration takes a certain number of flops, what
234
+ * is a reasonable interval to check for interrupts?
235
+ */
236
+ static size_t get_period_hint (size_t flops);
237
+
238
+ };
239
+
240
+
241
+
242
+ }; // namespace faiss
243
+
244
+
245
+
246
+ #endif