faiss 0.2.6 → 0.2.7

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 (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
@@ -35,6 +35,7 @@
35
35
  #include <faiss/impl/AuxIndexStructures.h>
36
36
  #include <faiss/impl/FaissAssert.h>
37
37
  #include <faiss/utils/Heap.h>
38
+ #include <faiss/utils/approx_topk_hamming/approx_topk_hamming.h>
38
39
  #include <faiss/utils/utils.h>
39
40
 
40
41
  static const size_t BLOCKSIZE_QUERY = 8192;
@@ -43,26 +44,13 @@ namespace faiss {
43
44
 
44
45
  size_t hamming_batch_size = 65536;
45
46
 
46
- const uint8_t hamdis_tab_ham_bytes[256] = {
47
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4,
48
- 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
49
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4,
50
- 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
51
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
52
- 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
53
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5,
54
- 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
55
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
56
- 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
57
- 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
58
-
59
47
  template <size_t nbits>
60
48
  void hammings(
61
- const uint64_t* bs1,
62
- const uint64_t* bs2,
49
+ const uint64_t* __restrict bs1,
50
+ const uint64_t* __restrict bs2,
63
51
  size_t n1,
64
52
  size_t n2,
65
- hamdis_t* dis)
53
+ hamdis_t* __restrict dis)
66
54
 
67
55
  {
68
56
  size_t i, j;
@@ -76,8 +64,8 @@ void hammings(
76
64
  }
77
65
 
78
66
  void hammings(
79
- const uint64_t* bs1,
80
- const uint64_t* bs2,
67
+ const uint64_t* __restrict bs1,
68
+ const uint64_t* __restrict bs2,
81
69
  size_t n1,
82
70
  size_t n2,
83
71
  size_t nwords,
@@ -95,12 +83,12 @@ void hammings(
95
83
  /* Count number of matches given a max threshold */
96
84
  template <size_t nbits>
97
85
  void hamming_count_thres(
98
- const uint64_t* bs1,
99
- const uint64_t* bs2,
86
+ const uint64_t* __restrict bs1,
87
+ const uint64_t* __restrict bs2,
100
88
  size_t n1,
101
89
  size_t n2,
102
90
  hamdis_t ht,
103
- size_t* nptr) {
91
+ size_t* __restrict nptr) {
104
92
  const size_t nwords = nbits / 64;
105
93
  size_t i, j, posm = 0;
106
94
  const uint64_t* bs2_ = bs2;
@@ -120,10 +108,10 @@ void hamming_count_thres(
120
108
 
121
109
  template <size_t nbits>
122
110
  void crosshamming_count_thres(
123
- const uint64_t* dbs,
111
+ const uint64_t* __restrict dbs,
124
112
  size_t n,
125
113
  int ht,
126
- size_t* nptr) {
114
+ size_t* __restrict nptr) {
127
115
  const size_t nwords = nbits / 64;
128
116
  size_t i, j, posm = 0;
129
117
  const uint64_t* bs1 = dbs;
@@ -142,13 +130,13 @@ void crosshamming_count_thres(
142
130
 
143
131
  template <size_t nbits>
144
132
  size_t match_hamming_thres(
145
- const uint64_t* bs1,
146
- const uint64_t* bs2,
133
+ const uint64_t* __restrict bs1,
134
+ const uint64_t* __restrict bs2,
147
135
  size_t n1,
148
136
  size_t n2,
149
137
  int ht,
150
- int64_t* idx,
151
- hamdis_t* hams) {
138
+ int64_t* __restrict idx,
139
+ hamdis_t* __restrict hams) {
152
140
  const size_t nwords = nbits / 64;
153
141
  size_t i, j, posm = 0;
154
142
  hamdis_t h;
@@ -181,12 +169,13 @@ size_t match_hamming_thres(
181
169
  template <class HammingComputer>
182
170
  static void hammings_knn_hc(
183
171
  int bytes_per_code,
184
- int_maxheap_array_t* ha,
185
- const uint8_t* bs1,
186
- const uint8_t* bs2,
172
+ int_maxheap_array_t* __restrict ha,
173
+ const uint8_t* __restrict bs1,
174
+ const uint8_t* __restrict bs2,
187
175
  size_t n2,
188
176
  bool order = true,
189
- bool init_heap = true) {
177
+ bool init_heap = true,
178
+ ApproxTopK_mode_t approx_topk_mode = ApproxTopK_mode_t::EXACT_TOPK) {
190
179
  size_t k = ha->k;
191
180
  if (init_heap)
192
181
  ha->heapify();
@@ -198,17 +187,44 @@ static void hammings_knn_hc(
198
187
  for (int64_t i = 0; i < ha->nh; i++) {
199
188
  HammingComputer hc(bs1 + i * bytes_per_code, bytes_per_code);
200
189
 
201
- const uint8_t* bs2_ = bs2 + j0 * bytes_per_code;
190
+ const uint8_t* __restrict bs2_ = bs2 + j0 * bytes_per_code;
202
191
  hamdis_t dis;
203
192
  hamdis_t* __restrict bh_val_ = ha->val + i * k;
204
193
  int64_t* __restrict bh_ids_ = ha->ids + i * k;
205
- size_t j;
206
- for (j = j0; j < j1; j++, bs2_ += bytes_per_code) {
207
- dis = hc.hamming(bs2_);
208
- if (dis < bh_val_[0]) {
209
- faiss::maxheap_replace_top<hamdis_t>(
210
- k, bh_val_, bh_ids_, dis, j);
211
- }
194
+
195
+ // if larger number of k is required, then ::bs_addn() needs to be
196
+ // used instead of ::addn()
197
+ #define HANDLE_APPROX(NB, BD) \
198
+ case ApproxTopK_mode_t::APPROX_TOPK_BUCKETS_B##NB##_D##BD: \
199
+ FAISS_THROW_IF_NOT_FMT( \
200
+ k <= NB * BD, \
201
+ "The chosen mode (%d) of approximate top-k supports " \
202
+ "up to %d values, but %zd is requested.", \
203
+ (int)(ApproxTopK_mode_t::APPROX_TOPK_BUCKETS_B##NB##_D##BD), \
204
+ NB * BD, \
205
+ k); \
206
+ HeapWithBucketsForHamming32< \
207
+ CMax<hamdis_t, int64_t>, \
208
+ NB, \
209
+ BD, \
210
+ HammingComputer>:: \
211
+ addn(j1 - j0, hc, bs2_, k, bh_val_, bh_ids_); \
212
+ break;
213
+
214
+ switch (approx_topk_mode) {
215
+ HANDLE_APPROX(8, 3)
216
+ HANDLE_APPROX(8, 2)
217
+ HANDLE_APPROX(16, 2)
218
+ HANDLE_APPROX(32, 2)
219
+ default: {
220
+ for (size_t j = j0; j < j1; j++, bs2_ += bytes_per_code) {
221
+ dis = hc.hamming(bs2_);
222
+ if (dis < bh_val_[0]) {
223
+ faiss::maxheap_replace_top<hamdis_t>(
224
+ k, bh_val_, bh_ids_, dis, j);
225
+ }
226
+ }
227
+ } break;
212
228
  }
213
229
  }
214
230
  }
@@ -220,13 +236,13 @@ static void hammings_knn_hc(
220
236
  template <class HammingComputer>
221
237
  static void hammings_knn_mc(
222
238
  int bytes_per_code,
223
- const uint8_t* a,
224
- const uint8_t* b,
239
+ const uint8_t* __restrict a,
240
+ const uint8_t* __restrict b,
225
241
  size_t na,
226
242
  size_t nb,
227
243
  size_t k,
228
- int32_t* distances,
229
- int64_t* labels) {
244
+ int32_t* __restrict distances,
245
+ int64_t* __restrict labels) {
230
246
  const int nBuckets = bytes_per_code * 8 + 1;
231
247
  std::vector<int> all_counters(na * nBuckets, 0);
232
248
  std::unique_ptr<int64_t[]> all_ids_per_dis(new int64_t[na * nBuckets * k]);
@@ -271,44 +287,6 @@ static void hammings_knn_mc(
271
287
  }
272
288
  }
273
289
 
274
- // works faster than the template version
275
- static void hammings_knn_hc_1(
276
- int_maxheap_array_t* ha,
277
- const uint64_t* bs1,
278
- const uint64_t* bs2,
279
- size_t n2,
280
- bool order = true,
281
- bool init_heap = true) {
282
- const size_t nwords = 1;
283
- size_t k = ha->k;
284
-
285
- if (init_heap) {
286
- ha->heapify();
287
- }
288
-
289
- #pragma omp parallel for
290
- for (int64_t i = 0; i < ha->nh; i++) {
291
- const uint64_t bs1_ = bs1[i];
292
- const uint64_t* bs2_ = bs2;
293
- hamdis_t dis;
294
- hamdis_t* bh_val_ = ha->val + i * k;
295
- hamdis_t bh_val_0 = bh_val_[0];
296
- int64_t* bh_ids_ = ha->ids + i * k;
297
- size_t j;
298
- for (j = 0; j < n2; j++, bs2_ += nwords) {
299
- dis = popcount64(bs1_ ^ *bs2_);
300
- if (dis < bh_val_0) {
301
- faiss::maxheap_replace_top<hamdis_t>(
302
- k, bh_val_, bh_ids_, dis, j);
303
- bh_val_0 = bh_val_[0];
304
- }
305
- }
306
- }
307
- if (order) {
308
- ha->reorder();
309
- }
310
- }
311
-
312
290
  /* Functions to maps vectors to bits. Assume proper allocation done beforehand,
313
291
  meaning that b should be be able to receive as many bits as x may produce. */
314
292
 
@@ -316,7 +294,7 @@ static void hammings_knn_hc_1(
316
294
  * dimension 0 corresponds to the least significant bit of b[0], or
317
295
  * equivalently to the lsb of the first byte that is stored.
318
296
  */
319
- void fvec2bitvec(const float* x, uint8_t* b, size_t d) {
297
+ void fvec2bitvec(const float* __restrict x, uint8_t* __restrict b, size_t d) {
320
298
  for (int i = 0; i < d; i += 8) {
321
299
  uint8_t w = 0;
322
300
  uint8_t mask = 1;
@@ -333,14 +311,22 @@ void fvec2bitvec(const float* x, uint8_t* b, size_t d) {
333
311
 
334
312
  /* Same but for n vectors.
335
313
  Ensure that the ouptut b is byte-aligned (pad with 0s). */
336
- void fvecs2bitvecs(const float* x, uint8_t* b, size_t d, size_t n) {
314
+ void fvecs2bitvecs(
315
+ const float* __restrict x,
316
+ uint8_t* __restrict b,
317
+ size_t d,
318
+ size_t n) {
337
319
  const int64_t ncodes = ((d + 7) / 8);
338
320
  #pragma omp parallel for if (n > 100000)
339
321
  for (int64_t i = 0; i < n; i++)
340
322
  fvec2bitvec(x + i * d, b + i * ncodes, d);
341
323
  }
342
324
 
343
- void bitvecs2fvecs(const uint8_t* b, float* x, size_t d, size_t n) {
325
+ void bitvecs2fvecs(
326
+ const uint8_t* __restrict b,
327
+ float* __restrict x,
328
+ size_t d,
329
+ size_t n) {
344
330
  const int64_t ncodes = ((d + 7) / 8);
345
331
  #pragma omp parallel for if (n > 100000)
346
332
  for (int64_t i = 0; i < n; i++) {
@@ -378,9 +364,9 @@ void bitvec_shuffle(
378
364
  size_t n,
379
365
  size_t da,
380
366
  size_t db,
381
- const int* order,
382
- const uint8_t* a,
383
- uint8_t* b) {
367
+ const int* __restrict order,
368
+ const uint8_t* __restrict a,
369
+ uint8_t* __restrict b) {
384
370
  for (size_t i = 0; i < db; i++) {
385
371
  FAISS_THROW_IF_NOT(order[i] >= 0 && order[i] < da);
386
372
  }
@@ -407,8 +393,8 @@ void bitvec_shuffle(
407
393
 
408
394
  /* Compute a set of Hamming distances */
409
395
  void hammings(
410
- const uint8_t* a,
411
- const uint8_t* b,
396
+ const uint8_t* __restrict a,
397
+ const uint8_t* __restrict b,
412
398
  size_t na,
413
399
  size_t nb,
414
400
  size_t ncodes,
@@ -434,9 +420,9 @@ void hammings(
434
420
  }
435
421
 
436
422
  void hammings_knn(
437
- int_maxheap_array_t* ha,
438
- const uint8_t* a,
439
- const uint8_t* b,
423
+ int_maxheap_array_t* __restrict ha,
424
+ const uint8_t* __restrict a,
425
+ const uint8_t* __restrict b,
440
426
  size_t nb,
441
427
  size_t ncodes,
442
428
  int order) {
@@ -444,54 +430,52 @@ void hammings_knn(
444
430
  }
445
431
 
446
432
  void hammings_knn_hc(
447
- int_maxheap_array_t* ha,
448
- const uint8_t* a,
449
- const uint8_t* b,
433
+ int_maxheap_array_t* __restrict ha,
434
+ const uint8_t* __restrict a,
435
+ const uint8_t* __restrict b,
450
436
  size_t nb,
451
437
  size_t ncodes,
452
- int order) {
438
+ int order,
439
+ ApproxTopK_mode_t approx_topk_mode) {
453
440
  switch (ncodes) {
454
441
  case 4:
455
442
  hammings_knn_hc<faiss::HammingComputer4>(
456
- 4, ha, a, b, nb, order, true);
443
+ 4, ha, a, b, nb, order, true, approx_topk_mode);
457
444
  break;
458
445
  case 8:
459
- hammings_knn_hc_1(ha, C64(a), C64(b), nb, order, true);
460
- // hammings_knn_hc<faiss::HammingComputer8>
461
- // (8, ha, a, b, nb, order, true);
446
+ hammings_knn_hc<faiss::HammingComputer8>(
447
+ 8, ha, a, b, nb, order, true, approx_topk_mode);
462
448
  break;
463
449
  case 16:
464
450
  hammings_knn_hc<faiss::HammingComputer16>(
465
- 16, ha, a, b, nb, order, true);
451
+ 16, ha, a, b, nb, order, true, approx_topk_mode);
466
452
  break;
467
453
  case 32:
468
454
  hammings_knn_hc<faiss::HammingComputer32>(
469
- 32, ha, a, b, nb, order, true);
455
+ 32, ha, a, b, nb, order, true, approx_topk_mode);
470
456
  break;
471
457
  default:
472
458
  hammings_knn_hc<faiss::HammingComputerDefault>(
473
- ncodes, ha, a, b, nb, order, true);
459
+ ncodes, ha, a, b, nb, order, true, approx_topk_mode);
474
460
  break;
475
461
  }
476
462
  }
477
463
 
478
464
  void hammings_knn_mc(
479
- const uint8_t* a,
480
- const uint8_t* b,
465
+ const uint8_t* __restrict a,
466
+ const uint8_t* __restrict b,
481
467
  size_t na,
482
468
  size_t nb,
483
469
  size_t k,
484
470
  size_t ncodes,
485
- int32_t* distances,
486
- int64_t* labels) {
471
+ int32_t* __restrict distances,
472
+ int64_t* __restrict labels) {
487
473
  switch (ncodes) {
488
474
  case 4:
489
475
  hammings_knn_mc<faiss::HammingComputer4>(
490
476
  4, a, b, na, nb, k, distances, labels);
491
477
  break;
492
478
  case 8:
493
- // TODO(hoss): Write analog to hammings_knn_hc_1
494
- // hammings_knn_hc_1 (ha, C64(a), C64(b), nb, order, true);
495
479
  hammings_knn_mc<faiss::HammingComputer8>(
496
480
  8, a, b, na, nb, k, distances, labels);
497
481
  break;
@@ -664,13 +648,13 @@ size_t match_hamming_thres(
664
648
 
665
649
  template <class HammingComputer>
666
650
  static void hamming_dis_inner_loop(
667
- const uint8_t* ca,
668
- const uint8_t* cb,
651
+ const uint8_t* __restrict ca,
652
+ const uint8_t* __restrict cb,
669
653
  size_t nb,
670
654
  size_t code_size,
671
655
  int k,
672
- hamdis_t* bh_val_,
673
- int64_t* bh_ids_) {
656
+ hamdis_t* __restrict bh_val_,
657
+ int64_t* __restrict bh_ids_) {
674
658
  HammingComputer hc(ca, code_size);
675
659
 
676
660
  for (size_t j = 0; j < nb; j++) {
@@ -683,9 +667,9 @@ static void hamming_dis_inner_loop(
683
667
  }
684
668
 
685
669
  void generalized_hammings_knn_hc(
686
- int_maxheap_array_t* ha,
687
- const uint8_t* a,
688
- const uint8_t* b,
670
+ int_maxheap_array_t* __restrict ha,
671
+ const uint8_t* __restrict a,
672
+ const uint8_t* __restrict b,
689
673
  size_t nb,
690
674
  size_t code_size,
691
675
  int ordered) {
@@ -697,11 +681,11 @@ void generalized_hammings_knn_hc(
697
681
 
698
682
  #pragma omp parallel for
699
683
  for (int i = 0; i < na; i++) {
700
- const uint8_t* ca = a + i * code_size;
701
- const uint8_t* cb = b;
684
+ const uint8_t* __restrict ca = a + i * code_size;
685
+ const uint8_t* __restrict cb = b;
702
686
 
703
- hamdis_t* bh_val_ = ha->val + i * k;
704
- int64_t* bh_ids_ = ha->ids + i * k;
687
+ hamdis_t* __restrict bh_val_ = ha->val + i * k;
688
+ int64_t* __restrict bh_ids_ = ha->ids + i * k;
705
689
 
706
690
  switch (code_size) {
707
691
  case 8:
@@ -19,6 +19,7 @@
19
19
  * - memory usage
20
20
  * - cache-misses when dealing with large volumes of data (fewer bits is better)
21
21
  *
22
+ * hamdis_t is defined in utils/hamming_distance/common.h
22
23
  */
23
24
 
24
25
  #ifndef FAISS_hamming_h
@@ -29,8 +30,10 @@
29
30
  #include <faiss/impl/platform_macros.h>
30
31
  #include <faiss/utils/Heap.h>
31
32
 
32
- /* The Hamming distance type */
33
- typedef int32_t hamdis_t;
33
+ // Low-level Hamming distance computations and hamdis_t.
34
+ #include <faiss/utils/hamming_distance/hamdis-inl.h>
35
+
36
+ #include <faiss/utils/approx_topk/mode.h>
34
37
 
35
38
  namespace faiss {
36
39
 
@@ -99,10 +102,6 @@ struct BitstringReader {
99
102
 
100
103
  FAISS_API extern size_t hamming_batch_size;
101
104
 
102
- inline int popcount64(uint64_t x) {
103
- return __builtin_popcountl(x);
104
- }
105
-
106
105
  /** Compute a set of Hamming distances between na and nb binary vectors
107
106
  *
108
107
  * @param a size na * nbytespercode
@@ -125,14 +124,18 @@ void hammings(
125
124
  * @param nb number of database vectors
126
125
  * @param ncodes size of the binary codes (bytes)
127
126
  * @param ordered if != 0: order the results by decreasing distance
128
- * (may be bottleneck for k/n > 0.01) */
127
+ * (may be bottleneck for k/n > 0.01)
128
+ * @param approx_topk_mode allows to use approximate top-k facilities
129
+ * to speedup heap
130
+ */
129
131
  void hammings_knn_hc(
130
132
  int_maxheap_array_t* ha,
131
133
  const uint8_t* a,
132
134
  const uint8_t* b,
133
135
  size_t nb,
134
136
  size_t ncodes,
135
- int ordered);
137
+ int ordered,
138
+ ApproxTopK_mode_t approx_topk_mode = ApproxTopK_mode_t::EXACT_TOPK);
136
139
 
137
140
  /* Legacy alias to hammings_knn_hc. */
138
141
  void hammings_knn(
@@ -209,9 +212,17 @@ void crosshamming_count_thres(
209
212
  /* compute the Hamming distances between two codewords of nwords*64 bits */
210
213
  hamdis_t hamming(const uint64_t* bs1, const uint64_t* bs2, size_t nwords);
211
214
 
212
- } // namespace faiss
215
+ /** generalized Hamming distances (= count number of code bytes that
216
+ are the same) */
217
+ void generalized_hammings_knn_hc(
218
+ int_maxheap_array_t* ha,
219
+ const uint8_t* a,
220
+ const uint8_t* b,
221
+ size_t nb,
222
+ size_t code_size,
223
+ int ordered = true);
213
224
 
214
- // inlined definitions of HammingComputerXX and GenHammingComputerXX
225
+ } // namespace faiss
215
226
 
216
227
  #include <faiss/utils/hamming-inl.h>
217
228