faiss 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/faiss/extconf.rb +1 -1
  4. data/lib/faiss/version.rb +1 -1
  5. data/lib/faiss.rb +2 -2
  6. data/vendor/faiss/faiss/AutoTune.cpp +15 -4
  7. data/vendor/faiss/faiss/AutoTune.h +0 -1
  8. data/vendor/faiss/faiss/Clustering.cpp +1 -5
  9. data/vendor/faiss/faiss/Clustering.h +0 -2
  10. data/vendor/faiss/faiss/IVFlib.h +0 -2
  11. data/vendor/faiss/faiss/Index.h +1 -2
  12. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +17 -3
  13. data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +10 -1
  14. data/vendor/faiss/faiss/IndexBinary.h +0 -1
  15. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +2 -1
  16. data/vendor/faiss/faiss/IndexBinaryFlat.h +4 -0
  17. data/vendor/faiss/faiss/IndexBinaryHash.cpp +1 -3
  18. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +273 -48
  19. data/vendor/faiss/faiss/IndexBinaryIVF.h +18 -11
  20. data/vendor/faiss/faiss/IndexFastScan.cpp +13 -10
  21. data/vendor/faiss/faiss/IndexFastScan.h +5 -1
  22. data/vendor/faiss/faiss/IndexFlat.cpp +16 -3
  23. data/vendor/faiss/faiss/IndexFlat.h +1 -1
  24. data/vendor/faiss/faiss/IndexFlatCodes.cpp +5 -0
  25. data/vendor/faiss/faiss/IndexFlatCodes.h +7 -2
  26. data/vendor/faiss/faiss/IndexHNSW.cpp +3 -6
  27. data/vendor/faiss/faiss/IndexHNSW.h +0 -1
  28. data/vendor/faiss/faiss/IndexIDMap.cpp +4 -4
  29. data/vendor/faiss/faiss/IndexIDMap.h +0 -2
  30. data/vendor/faiss/faiss/IndexIVF.cpp +155 -129
  31. data/vendor/faiss/faiss/IndexIVF.h +121 -61
  32. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +2 -2
  33. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +12 -11
  34. data/vendor/faiss/faiss/IndexIVFFastScan.h +6 -1
  35. data/vendor/faiss/faiss/IndexIVFPQ.cpp +221 -165
  36. data/vendor/faiss/faiss/IndexIVFPQ.h +1 -0
  37. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +6 -1
  38. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +0 -2
  39. data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -2
  40. data/vendor/faiss/faiss/IndexNNDescent.h +0 -1
  41. data/vendor/faiss/faiss/IndexNSG.cpp +1 -2
  42. data/vendor/faiss/faiss/IndexPQ.cpp +7 -9
  43. data/vendor/faiss/faiss/IndexRefine.cpp +1 -1
  44. data/vendor/faiss/faiss/IndexReplicas.cpp +3 -4
  45. data/vendor/faiss/faiss/IndexReplicas.h +0 -1
  46. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +8 -1
  47. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +7 -0
  48. data/vendor/faiss/faiss/IndexShards.cpp +26 -109
  49. data/vendor/faiss/faiss/IndexShards.h +2 -3
  50. data/vendor/faiss/faiss/IndexShardsIVF.cpp +246 -0
  51. data/vendor/faiss/faiss/IndexShardsIVF.h +42 -0
  52. data/vendor/faiss/faiss/MetaIndexes.cpp +86 -0
  53. data/vendor/faiss/faiss/MetaIndexes.h +29 -0
  54. data/vendor/faiss/faiss/MetricType.h +14 -0
  55. data/vendor/faiss/faiss/VectorTransform.cpp +8 -10
  56. data/vendor/faiss/faiss/VectorTransform.h +1 -3
  57. data/vendor/faiss/faiss/clone_index.cpp +232 -18
  58. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +25 -3
  59. data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +7 -0
  60. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +78 -0
  61. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +20 -6
  62. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +7 -1
  63. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +21 -7
  64. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +7 -0
  65. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +7 -0
  66. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +10 -3
  67. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +7 -1
  68. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +11 -3
  69. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +25 -2
  70. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +76 -29
  71. data/vendor/faiss/faiss/gpu/GpuCloner.h +2 -2
  72. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +14 -13
  73. data/vendor/faiss/faiss/gpu/GpuDistance.h +18 -6
  74. data/vendor/faiss/faiss/gpu/GpuIndex.h +23 -21
  75. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +10 -10
  76. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -12
  77. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +29 -50
  78. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +3 -3
  79. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +8 -8
  80. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +4 -4
  81. data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +2 -5
  82. data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +9 -7
  83. data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +4 -4
  84. data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +2 -2
  85. data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +1 -1
  86. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +55 -6
  87. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +20 -6
  88. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +95 -25
  89. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +67 -16
  90. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +4 -4
  91. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +7 -7
  92. data/vendor/faiss/faiss/gpu/test/TestUtils.h +4 -4
  93. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
  94. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
  95. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +0 -7
  96. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +9 -9
  97. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +1 -1
  98. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +2 -7
  99. data/vendor/faiss/faiss/impl/CodePacker.cpp +67 -0
  100. data/vendor/faiss/faiss/impl/CodePacker.h +71 -0
  101. data/vendor/faiss/faiss/impl/DistanceComputer.h +0 -2
  102. data/vendor/faiss/faiss/impl/HNSW.cpp +3 -7
  103. data/vendor/faiss/faiss/impl/HNSW.h +6 -9
  104. data/vendor/faiss/faiss/impl/IDSelector.cpp +1 -1
  105. data/vendor/faiss/faiss/impl/IDSelector.h +39 -1
  106. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +62 -51
  107. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +11 -12
  108. data/vendor/faiss/faiss/impl/NNDescent.cpp +3 -9
  109. data/vendor/faiss/faiss/impl/NNDescent.h +10 -10
  110. data/vendor/faiss/faiss/impl/NSG.cpp +1 -6
  111. data/vendor/faiss/faiss/impl/NSG.h +4 -7
  112. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +1 -15
  113. data/vendor/faiss/faiss/impl/PolysemousTraining.h +11 -10
  114. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +0 -7
  115. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +25 -12
  116. data/vendor/faiss/faiss/impl/ProductQuantizer.h +2 -4
  117. data/vendor/faiss/faiss/impl/Quantizer.h +6 -3
  118. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +796 -174
  119. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +16 -8
  120. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +3 -5
  121. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +4 -4
  122. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +3 -3
  123. data/vendor/faiss/faiss/impl/ThreadedIndex.h +4 -4
  124. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +291 -0
  125. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +74 -0
  126. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +123 -0
  127. data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +102 -0
  128. data/vendor/faiss/faiss/impl/index_read.cpp +13 -10
  129. data/vendor/faiss/faiss/impl/index_write.cpp +3 -4
  130. data/vendor/faiss/faiss/impl/kmeans1d.cpp +0 -1
  131. data/vendor/faiss/faiss/impl/kmeans1d.h +3 -3
  132. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
  133. data/vendor/faiss/faiss/impl/platform_macros.h +61 -0
  134. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +48 -4
  135. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +18 -4
  136. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +2 -2
  137. data/vendor/faiss/faiss/index_factory.cpp +8 -10
  138. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +29 -12
  139. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +8 -2
  140. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
  141. data/vendor/faiss/faiss/invlists/DirectMap.h +2 -4
  142. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +118 -18
  143. data/vendor/faiss/faiss/invlists/InvertedLists.h +44 -4
  144. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +3 -3
  145. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  146. data/vendor/faiss/faiss/python/python_callbacks.cpp +1 -1
  147. data/vendor/faiss/faiss/python/python_callbacks.h +1 -1
  148. data/vendor/faiss/faiss/utils/AlignedTable.h +3 -1
  149. data/vendor/faiss/faiss/utils/Heap.cpp +139 -3
  150. data/vendor/faiss/faiss/utils/Heap.h +35 -1
  151. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +84 -0
  152. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +196 -0
  153. data/vendor/faiss/faiss/utils/approx_topk/generic.h +138 -0
  154. data/vendor/faiss/faiss/utils/approx_topk/mode.h +34 -0
  155. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +367 -0
  156. data/vendor/faiss/faiss/utils/distances.cpp +61 -7
  157. data/vendor/faiss/faiss/utils/distances.h +11 -0
  158. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +346 -0
  159. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +36 -0
  160. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +42 -0
  161. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +40 -0
  162. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +352 -0
  163. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +32 -0
  164. data/vendor/faiss/faiss/utils/distances_simd.cpp +515 -327
  165. data/vendor/faiss/faiss/utils/extra_distances-inl.h +17 -1
  166. data/vendor/faiss/faiss/utils/extra_distances.cpp +37 -8
  167. data/vendor/faiss/faiss/utils/extra_distances.h +2 -1
  168. data/vendor/faiss/faiss/utils/fp16-fp16c.h +7 -0
  169. data/vendor/faiss/faiss/utils/fp16-inl.h +7 -0
  170. data/vendor/faiss/faiss/utils/fp16.h +7 -0
  171. data/vendor/faiss/faiss/utils/hamming-inl.h +0 -456
  172. data/vendor/faiss/faiss/utils/hamming.cpp +104 -120
  173. data/vendor/faiss/faiss/utils/hamming.h +21 -10
  174. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +535 -0
  175. data/vendor/faiss/faiss/utils/hamming_distance/common.h +48 -0
  176. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +519 -0
  177. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +26 -0
  178. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +614 -0
  179. data/vendor/faiss/faiss/utils/partitioning.cpp +21 -25
  180. data/vendor/faiss/faiss/utils/simdlib_avx2.h +344 -3
  181. data/vendor/faiss/faiss/utils/simdlib_emulated.h +390 -0
  182. data/vendor/faiss/faiss/utils/simdlib_neon.h +655 -130
  183. data/vendor/faiss/faiss/utils/sorting.cpp +692 -0
  184. data/vendor/faiss/faiss/utils/sorting.h +71 -0
  185. data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +165 -0
  186. data/vendor/faiss/faiss/utils/utils.cpp +4 -176
  187. data/vendor/faiss/faiss/utils/utils.h +2 -9
  188. metadata +29 -3
  189. data/vendor/faiss/faiss/gpu/GpuClonerOptions.cpp +0 -26
@@ -8,6 +8,7 @@
8
8
  /** In this file are the implementations of extra metrics beyond L2
9
9
  * and inner product */
10
10
 
11
+ #include <faiss/MetricType.h>
11
12
  #include <faiss/utils/distances.h>
12
13
  #include <type_traits>
13
14
 
@@ -17,12 +18,13 @@ template <MetricType mt>
17
18
  struct VectorDistance {
18
19
  size_t d;
19
20
  float metric_arg;
21
+ static constexpr bool is_similarity = is_similarity_metric(mt);
20
22
 
21
23
  inline float operator()(const float* x, const float* y) const;
22
24
 
23
25
  // heap template to use for this type of metric
24
26
  using C = typename std::conditional<
25
- mt == METRIC_INNER_PRODUCT,
27
+ is_similarity_metric(mt),
26
28
  CMin<float, int64_t>,
27
29
  CMax<float, int64_t>>::type;
28
30
  };
@@ -114,4 +116,18 @@ inline float VectorDistance<METRIC_JensenShannon>::operator()(
114
116
  return 0.5 * accu;
115
117
  }
116
118
 
119
+ template <>
120
+ inline float VectorDistance<METRIC_Jaccard>::operator()(
121
+ const float* x,
122
+ const float* y) const {
123
+ // WARNING: this distance is defined only for positive input vectors.
124
+ // Providing vectors with negative values would lead to incorrect results.
125
+ float accu_num = 0, accu_den = 0;
126
+ for (size_t i = 0; i < d; i++) {
127
+ accu_num += fmin(x[i], y[i]);
128
+ accu_den += fmax(x[i], y[i]);
129
+ }
130
+ return accu_num / accu_den;
131
+ }
132
+
117
133
  } // namespace faiss
@@ -50,14 +50,14 @@ void pairwise_extra_distances_template(
50
50
  }
51
51
  }
52
52
 
53
- template <class VD>
53
+ template <class VD, class C>
54
54
  void knn_extra_metrics_template(
55
55
  VD vd,
56
56
  const float* x,
57
57
  const float* y,
58
58
  size_t nx,
59
59
  size_t ny,
60
- float_maxheap_array_t* res) {
60
+ HeapArray<C>* res) {
61
61
  size_t k = res->k;
62
62
  size_t d = vd.d;
63
63
  size_t check_period = InterruptCallback::get_period_hint(ny * d);
@@ -74,16 +74,21 @@ void knn_extra_metrics_template(
74
74
  float* simi = res->get_val(i);
75
75
  int64_t* idxi = res->get_ids(i);
76
76
 
77
- maxheap_heapify(k, simi, idxi);
77
+ // maxheap_heapify(k, simi, idxi);
78
+ heap_heapify<C>(k, simi, idxi);
78
79
  for (j = 0; j < ny; j++) {
79
80
  float disij = vd(x_i, y_j);
80
81
 
81
- if (disij < simi[0]) {
82
- maxheap_replace_top(k, simi, idxi, disij, j);
82
+ // if (disij < simi[0]) {
83
+ if ((!vd.is_similarity && (disij < simi[0])) ||
84
+ (vd.is_similarity && (disij > simi[0]))) {
85
+ // maxheap_replace_top(k, simi, idxi, disij, j);
86
+ heap_replace_top<C>(k, simi, idxi, disij, j);
83
87
  }
84
88
  y_j += d;
85
89
  }
86
- maxheap_reorder(k, simi, idxi);
90
+ // maxheap_reorder(k, simi, idxi);
91
+ heap_reorder<C>(k, simi, idxi);
87
92
  }
88
93
  InterruptCallback::check();
89
94
  }
@@ -92,7 +97,7 @@ void knn_extra_metrics_template(
92
97
  template <class VD>
93
98
  struct ExtraDistanceComputer : FlatCodesDistanceComputer {
94
99
  VD vd;
95
- Index::idx_t nb;
100
+ idx_t nb;
96
101
  const float* q;
97
102
  const float* b;
98
103
 
@@ -158,12 +163,14 @@ void pairwise_extra_distances(
158
163
  HANDLE_VAR(BrayCurtis);
159
164
  HANDLE_VAR(JensenShannon);
160
165
  HANDLE_VAR(Lp);
166
+ HANDLE_VAR(Jaccard);
161
167
  #undef HANDLE_VAR
162
168
  default:
163
169
  FAISS_THROW_MSG("metric type not implemented");
164
170
  }
165
171
  }
166
172
 
173
+ template <class C>
167
174
  void knn_extra_metrics(
168
175
  const float* x,
169
176
  const float* y,
@@ -172,7 +179,7 @@ void knn_extra_metrics(
172
179
  size_t ny,
173
180
  MetricType mt,
174
181
  float metric_arg,
175
- float_maxheap_array_t* res) {
182
+ HeapArray<C>* res) {
176
183
  switch (mt) {
177
184
  #define HANDLE_VAR(kw) \
178
185
  case METRIC_##kw: { \
@@ -187,12 +194,33 @@ void knn_extra_metrics(
187
194
  HANDLE_VAR(BrayCurtis);
188
195
  HANDLE_VAR(JensenShannon);
189
196
  HANDLE_VAR(Lp);
197
+ HANDLE_VAR(Jaccard);
190
198
  #undef HANDLE_VAR
191
199
  default:
192
200
  FAISS_THROW_MSG("metric type not implemented");
193
201
  }
194
202
  }
195
203
 
204
+ template void knn_extra_metrics<CMax<float, int64_t>>(
205
+ const float* x,
206
+ const float* y,
207
+ size_t d,
208
+ size_t nx,
209
+ size_t ny,
210
+ MetricType mt,
211
+ float metric_arg,
212
+ HeapArray<CMax<float, int64_t>>* res);
213
+
214
+ template void knn_extra_metrics<CMin<float, int64_t>>(
215
+ const float* x,
216
+ const float* y,
217
+ size_t d,
218
+ size_t nx,
219
+ size_t ny,
220
+ MetricType mt,
221
+ float metric_arg,
222
+ HeapArray<CMin<float, int64_t>>* res);
223
+
196
224
  FlatCodesDistanceComputer* get_extra_distance_computer(
197
225
  size_t d,
198
226
  MetricType mt,
@@ -213,6 +241,7 @@ FlatCodesDistanceComputer* get_extra_distance_computer(
213
241
  HANDLE_VAR(BrayCurtis);
214
242
  HANDLE_VAR(JensenShannon);
215
243
  HANDLE_VAR(Lp);
244
+ HANDLE_VAR(Jaccard);
216
245
  #undef HANDLE_VAR
217
246
  default:
218
247
  FAISS_THROW_MSG("metric type not implemented");
@@ -33,6 +33,7 @@ void pairwise_extra_distances(
33
33
  int64_t ldb = -1,
34
34
  int64_t ldd = -1);
35
35
 
36
+ template <class C>
36
37
  void knn_extra_metrics(
37
38
  const float* x,
38
39
  const float* y,
@@ -41,7 +42,7 @@ void knn_extra_metrics(
41
42
  size_t ny,
42
43
  MetricType mt,
43
44
  float metric_arg,
44
- float_maxheap_array_t* res);
45
+ HeapArray<C>* res);
45
46
 
46
47
  /** get a DistanceComputer that refers to this type of distance and
47
48
  * indexes a flat array of size nb */
@@ -1,3 +1,10 @@
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
+
1
8
  #pragma once
2
9
 
3
10
  #include <immintrin.h>
@@ -1,3 +1,10 @@
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
+
1
8
  #pragma once
2
9
 
3
10
  #include <algorithm>
@@ -1,3 +1,10 @@
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
+
1
8
  #pragma once
2
9
 
3
10
  #include <cstdint>
@@ -7,61 +7,6 @@
7
7
 
8
8
  namespace faiss {
9
9
 
10
- extern const uint8_t hamdis_tab_ham_bytes[256];
11
-
12
- /* Elementary Hamming distance computation: unoptimized */
13
- template <size_t nbits, typename T>
14
- inline T hamming(const uint8_t* bs1, const uint8_t* bs2) {
15
- const size_t nbytes = nbits / 8;
16
- size_t i;
17
- T h = 0;
18
- for (i = 0; i < nbytes; i++) {
19
- h += (T)hamdis_tab_ham_bytes[bs1[i] ^ bs2[i]];
20
- }
21
- return h;
22
- }
23
-
24
- /* Hamming distances for multiples of 64 bits */
25
- template <size_t nbits>
26
- inline hamdis_t hamming(const uint64_t* bs1, const uint64_t* bs2) {
27
- const size_t nwords = nbits / 64;
28
- size_t i;
29
- hamdis_t h = 0;
30
- for (i = 0; i < nwords; i++) {
31
- h += popcount64(bs1[i] ^ bs2[i]);
32
- }
33
- return h;
34
- }
35
-
36
- /* specialized (optimized) functions */
37
- template <>
38
- inline hamdis_t hamming<64>(const uint64_t* pa, const uint64_t* pb) {
39
- return popcount64(pa[0] ^ pb[0]);
40
- }
41
-
42
- template <>
43
- inline hamdis_t hamming<128>(const uint64_t* pa, const uint64_t* pb) {
44
- return popcount64(pa[0] ^ pb[0]) + popcount64(pa[1] ^ pb[1]);
45
- }
46
-
47
- template <>
48
- inline hamdis_t hamming<256>(const uint64_t* pa, const uint64_t* pb) {
49
- return popcount64(pa[0] ^ pb[0]) + popcount64(pa[1] ^ pb[1]) +
50
- popcount64(pa[2] ^ pb[2]) + popcount64(pa[3] ^ pb[3]);
51
- }
52
-
53
- /* Hamming distances for multiple of 64 bits */
54
- inline hamdis_t hamming(
55
- const uint64_t* bs1,
56
- const uint64_t* bs2,
57
- size_t nwords) {
58
- hamdis_t h = 0;
59
- for (size_t i = 0; i < nwords; i++) {
60
- h += popcount64(bs1[i] ^ bs2[i]);
61
- }
62
- return h;
63
- }
64
-
65
10
  // BitstringWriter and BitstringReader functions
66
11
  inline BitstringWriter::BitstringWriter(uint8_t* code, size_t code_size)
67
12
  : code(code), code_size(code_size), i(0) {
@@ -119,407 +64,6 @@ inline uint64_t BitstringReader::read(int nbit) {
119
64
  }
120
65
  }
121
66
 
122
- /******************************************************************
123
- * The HammingComputer series of classes compares a single code of
124
- * size 4 to 32 to incoming codes. They are intended for use as a
125
- * template class where it would be inefficient to switch on the code
126
- * size in the inner loop. Hopefully the compiler will inline the
127
- * hamming() functions and put the a0, a1, ... in registers.
128
- ******************************************************************/
129
-
130
- struct HammingComputer4 {
131
- uint32_t a0;
132
-
133
- HammingComputer4() {}
134
-
135
- HammingComputer4(const uint8_t* a, int code_size) {
136
- set(a, code_size);
137
- }
138
-
139
- void set(const uint8_t* a, int code_size) {
140
- assert(code_size == 4);
141
- a0 = *(uint32_t*)a;
142
- }
143
-
144
- inline int hamming(const uint8_t* b) const {
145
- return popcount64(*(uint32_t*)b ^ a0);
146
- }
147
- };
148
-
149
- struct HammingComputer8 {
150
- uint64_t a0;
151
-
152
- HammingComputer8() {}
153
-
154
- HammingComputer8(const uint8_t* a, int code_size) {
155
- set(a, code_size);
156
- }
157
-
158
- void set(const uint8_t* a, int code_size) {
159
- assert(code_size == 8);
160
- a0 = *(uint64_t*)a;
161
- }
162
-
163
- inline int hamming(const uint8_t* b) const {
164
- return popcount64(*(uint64_t*)b ^ a0);
165
- }
166
- };
167
-
168
- struct HammingComputer16 {
169
- uint64_t a0, a1;
170
-
171
- HammingComputer16() {}
172
-
173
- HammingComputer16(const uint8_t* a8, int code_size) {
174
- set(a8, code_size);
175
- }
176
-
177
- void set(const uint8_t* a8, int code_size) {
178
- assert(code_size == 16);
179
- const uint64_t* a = (uint64_t*)a8;
180
- a0 = a[0];
181
- a1 = a[1];
182
- }
183
-
184
- inline int hamming(const uint8_t* b8) const {
185
- const uint64_t* b = (uint64_t*)b8;
186
- return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1);
187
- }
188
- };
189
-
190
- // when applied to an array, 1/2 of the 64-bit accesses are unaligned.
191
- // This incurs a penalty of ~10% wrt. fully aligned accesses.
192
- struct HammingComputer20 {
193
- uint64_t a0, a1;
194
- uint32_t a2;
195
-
196
- HammingComputer20() {}
197
-
198
- HammingComputer20(const uint8_t* a8, int code_size) {
199
- set(a8, code_size);
200
- }
201
-
202
- void set(const uint8_t* a8, int code_size) {
203
- assert(code_size == 20);
204
- const uint64_t* a = (uint64_t*)a8;
205
- a0 = a[0];
206
- a1 = a[1];
207
- a2 = a[2];
208
- }
209
-
210
- inline int hamming(const uint8_t* b8) const {
211
- const uint64_t* b = (uint64_t*)b8;
212
- return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
213
- popcount64(*(uint32_t*)(b + 2) ^ a2);
214
- }
215
- };
216
-
217
- struct HammingComputer32 {
218
- uint64_t a0, a1, a2, a3;
219
-
220
- HammingComputer32() {}
221
-
222
- HammingComputer32(const uint8_t* a8, int code_size) {
223
- set(a8, code_size);
224
- }
225
-
226
- void set(const uint8_t* a8, int code_size) {
227
- assert(code_size == 32);
228
- const uint64_t* a = (uint64_t*)a8;
229
- a0 = a[0];
230
- a1 = a[1];
231
- a2 = a[2];
232
- a3 = a[3];
233
- }
234
-
235
- inline int hamming(const uint8_t* b8) const {
236
- const uint64_t* b = (uint64_t*)b8;
237
- return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
238
- popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3);
239
- }
240
- };
241
-
242
- struct HammingComputer64 {
243
- uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
244
-
245
- HammingComputer64() {}
246
-
247
- HammingComputer64(const uint8_t* a8, int code_size) {
248
- set(a8, code_size);
249
- }
250
-
251
- void set(const uint8_t* a8, int code_size) {
252
- assert(code_size == 64);
253
- const uint64_t* a = (uint64_t*)a8;
254
- a0 = a[0];
255
- a1 = a[1];
256
- a2 = a[2];
257
- a3 = a[3];
258
- a4 = a[4];
259
- a5 = a[5];
260
- a6 = a[6];
261
- a7 = a[7];
262
- }
263
-
264
- inline int hamming(const uint8_t* b8) const {
265
- const uint64_t* b = (uint64_t*)b8;
266
- return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
267
- popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3) +
268
- popcount64(b[4] ^ a4) + popcount64(b[5] ^ a5) +
269
- popcount64(b[6] ^ a6) + popcount64(b[7] ^ a7);
270
- }
271
- };
272
-
273
- struct HammingComputerDefault {
274
- const uint8_t* a8;
275
- int quotient8;
276
- int remainder8;
277
-
278
- HammingComputerDefault() {}
279
-
280
- HammingComputerDefault(const uint8_t* a8, int code_size) {
281
- set(a8, code_size);
282
- }
283
-
284
- void set(const uint8_t* a8, int code_size) {
285
- this->a8 = a8;
286
- quotient8 = code_size / 8;
287
- remainder8 = code_size % 8;
288
- }
289
-
290
- int hamming(const uint8_t* b8) const {
291
- int accu = 0;
292
-
293
- const uint64_t* a64 = reinterpret_cast<const uint64_t*>(a8);
294
- const uint64_t* b64 = reinterpret_cast<const uint64_t*>(b8);
295
- int i = 0, len = quotient8;
296
- switch (len & 7) {
297
- default:
298
- while (len > 7) {
299
- len -= 8;
300
- accu += popcount64(a64[i] ^ b64[i]);
301
- i++;
302
- case 7:
303
- accu += popcount64(a64[i] ^ b64[i]);
304
- i++;
305
- case 6:
306
- accu += popcount64(a64[i] ^ b64[i]);
307
- i++;
308
- case 5:
309
- accu += popcount64(a64[i] ^ b64[i]);
310
- i++;
311
- case 4:
312
- accu += popcount64(a64[i] ^ b64[i]);
313
- i++;
314
- case 3:
315
- accu += popcount64(a64[i] ^ b64[i]);
316
- i++;
317
- case 2:
318
- accu += popcount64(a64[i] ^ b64[i]);
319
- i++;
320
- case 1:
321
- accu += popcount64(a64[i] ^ b64[i]);
322
- i++;
323
- }
324
- }
325
- if (remainder8) {
326
- const uint8_t* a = a8 + 8 * quotient8;
327
- const uint8_t* b = b8 + 8 * quotient8;
328
- switch (remainder8) {
329
- case 7:
330
- accu += hamdis_tab_ham_bytes[a[6] ^ b[6]];
331
- case 6:
332
- accu += hamdis_tab_ham_bytes[a[5] ^ b[5]];
333
- case 5:
334
- accu += hamdis_tab_ham_bytes[a[4] ^ b[4]];
335
- case 4:
336
- accu += hamdis_tab_ham_bytes[a[3] ^ b[3]];
337
- case 3:
338
- accu += hamdis_tab_ham_bytes[a[2] ^ b[2]];
339
- case 2:
340
- accu += hamdis_tab_ham_bytes[a[1] ^ b[1]];
341
- case 1:
342
- accu += hamdis_tab_ham_bytes[a[0] ^ b[0]];
343
- default:
344
- break;
345
- }
346
- }
347
-
348
- return accu;
349
- }
350
- };
351
-
352
- // more inefficient than HammingComputerDefault (obsolete)
353
- struct HammingComputerM8 {
354
- const uint64_t* a;
355
- int n;
356
-
357
- HammingComputerM8() {}
358
-
359
- HammingComputerM8(const uint8_t* a8, int code_size) {
360
- set(a8, code_size);
361
- }
362
-
363
- void set(const uint8_t* a8, int code_size) {
364
- assert(code_size % 8 == 0);
365
- a = (uint64_t*)a8;
366
- n = code_size / 8;
367
- }
368
-
369
- int hamming(const uint8_t* b8) const {
370
- const uint64_t* b = (uint64_t*)b8;
371
- int accu = 0;
372
- for (int i = 0; i < n; i++)
373
- accu += popcount64(a[i] ^ b[i]);
374
- return accu;
375
- }
376
- };
377
-
378
- // more inefficient than HammingComputerDefault (obsolete)
379
- struct HammingComputerM4 {
380
- const uint32_t* a;
381
- int n;
382
-
383
- HammingComputerM4() {}
384
-
385
- HammingComputerM4(const uint8_t* a4, int code_size) {
386
- set(a4, code_size);
387
- }
388
-
389
- void set(const uint8_t* a4, int code_size) {
390
- assert(code_size % 4 == 0);
391
- a = (uint32_t*)a4;
392
- n = code_size / 4;
393
- }
394
-
395
- int hamming(const uint8_t* b8) const {
396
- const uint32_t* b = (uint32_t*)b8;
397
- int accu = 0;
398
- for (int i = 0; i < n; i++)
399
- accu += popcount64(a[i] ^ b[i]);
400
- return accu;
401
- }
402
- };
403
-
404
- /***************************************************************************
405
- * Equivalence with a template class when code size is known at compile time
406
- **************************************************************************/
407
-
408
- // default template
409
- template <int CODE_SIZE>
410
- struct HammingComputer : HammingComputerDefault {
411
- HammingComputer(const uint8_t* a, int code_size)
412
- : HammingComputerDefault(a, code_size) {}
413
- };
414
-
415
- #define SPECIALIZED_HC(CODE_SIZE) \
416
- template <> \
417
- struct HammingComputer<CODE_SIZE> : HammingComputer##CODE_SIZE { \
418
- HammingComputer(const uint8_t* a) \
419
- : HammingComputer##CODE_SIZE(a, CODE_SIZE) {} \
420
- }
421
-
422
- SPECIALIZED_HC(4);
423
- SPECIALIZED_HC(8);
424
- SPECIALIZED_HC(16);
425
- SPECIALIZED_HC(20);
426
- SPECIALIZED_HC(32);
427
- SPECIALIZED_HC(64);
428
-
429
- #undef SPECIALIZED_HC
430
-
431
- /***************************************************************************
432
- * generalized Hamming = number of bytes that are different between
433
- * two codes.
434
- ***************************************************************************/
435
-
436
- inline int generalized_hamming_64(uint64_t a) {
437
- a |= a >> 1;
438
- a |= a >> 2;
439
- a |= a >> 4;
440
- a &= 0x0101010101010101UL;
441
- return popcount64(a);
442
- }
443
-
444
- struct GenHammingComputer8 {
445
- uint64_t a0;
446
-
447
- GenHammingComputer8(const uint8_t* a, int code_size) {
448
- assert(code_size == 8);
449
- a0 = *(uint64_t*)a;
450
- }
451
-
452
- inline int hamming(const uint8_t* b) const {
453
- return generalized_hamming_64(*(uint64_t*)b ^ a0);
454
- }
455
- };
456
-
457
- struct GenHammingComputer16 {
458
- uint64_t a0, a1;
459
- GenHammingComputer16(const uint8_t* a8, int code_size) {
460
- assert(code_size == 16);
461
- const uint64_t* a = (uint64_t*)a8;
462
- a0 = a[0];
463
- a1 = a[1];
464
- }
465
-
466
- inline int hamming(const uint8_t* b8) const {
467
- const uint64_t* b = (uint64_t*)b8;
468
- return generalized_hamming_64(b[0] ^ a0) +
469
- generalized_hamming_64(b[1] ^ a1);
470
- }
471
- };
472
-
473
- struct GenHammingComputer32 {
474
- uint64_t a0, a1, a2, a3;
475
-
476
- GenHammingComputer32(const uint8_t* a8, int code_size) {
477
- assert(code_size == 32);
478
- const uint64_t* a = (uint64_t*)a8;
479
- a0 = a[0];
480
- a1 = a[1];
481
- a2 = a[2];
482
- a3 = a[3];
483
- }
484
-
485
- inline int hamming(const uint8_t* b8) const {
486
- const uint64_t* b = (uint64_t*)b8;
487
- return generalized_hamming_64(b[0] ^ a0) +
488
- generalized_hamming_64(b[1] ^ a1) +
489
- generalized_hamming_64(b[2] ^ a2) +
490
- generalized_hamming_64(b[3] ^ a3);
491
- }
492
- };
493
-
494
- struct GenHammingComputerM8 {
495
- const uint64_t* a;
496
- int n;
497
-
498
- GenHammingComputerM8(const uint8_t* a8, int code_size) {
499
- assert(code_size % 8 == 0);
500
- a = (uint64_t*)a8;
501
- n = code_size / 8;
502
- }
503
-
504
- int hamming(const uint8_t* b8) const {
505
- const uint64_t* b = (uint64_t*)b8;
506
- int accu = 0;
507
- for (int i = 0; i < n; i++)
508
- accu += generalized_hamming_64(a[i] ^ b[i]);
509
- return accu;
510
- }
511
- };
512
-
513
- /** generalized Hamming distances (= count number of code bytes that
514
- are the same) */
515
- void generalized_hammings_knn_hc(
516
- int_maxheap_array_t* ha,
517
- const uint8_t* a,
518
- const uint8_t* b,
519
- size_t nb,
520
- size_t code_size,
521
- int ordered = true);
522
-
523
67
  /** This class maintains a list of best distances seen so far.
524
68
  *
525
69
  * Since the distances are in a limited range (0 to nbit), the