faiss 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +16 -4
  5. data/ext/faiss/ext.cpp +12 -308
  6. data/ext/faiss/extconf.rb +6 -3
  7. data/ext/faiss/index.cpp +189 -0
  8. data/ext/faiss/index_binary.cpp +75 -0
  9. data/ext/faiss/kmeans.cpp +40 -0
  10. data/ext/faiss/numo.hpp +867 -0
  11. data/ext/faiss/pca_matrix.cpp +33 -0
  12. data/ext/faiss/product_quantizer.cpp +53 -0
  13. data/ext/faiss/utils.cpp +13 -0
  14. data/ext/faiss/utils.h +5 -0
  15. data/lib/faiss.rb +0 -5
  16. data/lib/faiss/version.rb +1 -1
  17. data/vendor/faiss/faiss/AutoTune.cpp +36 -33
  18. data/vendor/faiss/faiss/AutoTune.h +6 -3
  19. data/vendor/faiss/faiss/Clustering.cpp +16 -12
  20. data/vendor/faiss/faiss/Index.cpp +3 -4
  21. data/vendor/faiss/faiss/Index.h +3 -3
  22. data/vendor/faiss/faiss/IndexBinary.cpp +3 -4
  23. data/vendor/faiss/faiss/IndexBinary.h +1 -1
  24. data/vendor/faiss/faiss/IndexBinaryHash.cpp +2 -12
  25. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +1 -2
  26. data/vendor/faiss/faiss/IndexFlat.cpp +0 -148
  27. data/vendor/faiss/faiss/IndexFlat.h +0 -51
  28. data/vendor/faiss/faiss/IndexHNSW.cpp +4 -5
  29. data/vendor/faiss/faiss/IndexIVF.cpp +118 -31
  30. data/vendor/faiss/faiss/IndexIVF.h +22 -15
  31. data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -3
  32. data/vendor/faiss/faiss/IndexIVFFlat.h +2 -1
  33. data/vendor/faiss/faiss/IndexIVFPQ.cpp +39 -15
  34. data/vendor/faiss/faiss/IndexIVFPQ.h +25 -9
  35. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1116 -0
  36. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +166 -0
  37. data/vendor/faiss/faiss/IndexIVFPQR.cpp +8 -9
  38. data/vendor/faiss/faiss/IndexIVFPQR.h +2 -1
  39. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +1 -2
  40. data/vendor/faiss/faiss/IndexPQ.cpp +34 -18
  41. data/vendor/faiss/faiss/IndexPQFastScan.cpp +536 -0
  42. data/vendor/faiss/faiss/IndexPQFastScan.h +111 -0
  43. data/vendor/faiss/faiss/IndexPreTransform.cpp +47 -0
  44. data/vendor/faiss/faiss/IndexPreTransform.h +2 -0
  45. data/vendor/faiss/faiss/IndexRefine.cpp +256 -0
  46. data/vendor/faiss/faiss/IndexRefine.h +73 -0
  47. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +2 -2
  48. data/vendor/faiss/faiss/IndexScalarQuantizer.h +1 -1
  49. data/vendor/faiss/faiss/gpu/GpuDistance.h +1 -1
  50. data/vendor/faiss/faiss/gpu/GpuIndex.h +16 -9
  51. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +8 -1
  52. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -11
  53. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +19 -2
  54. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +28 -2
  55. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +24 -14
  56. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +29 -2
  57. data/vendor/faiss/faiss/gpu/GpuResources.h +4 -0
  58. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +60 -27
  59. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +28 -6
  60. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +547 -0
  61. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +51 -0
  62. data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +3 -3
  63. data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +3 -2
  64. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +274 -0
  65. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +7 -2
  66. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +5 -1
  67. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +231 -0
  68. data/vendor/faiss/faiss/gpu/test/TestUtils.h +33 -0
  69. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -0
  70. data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +6 -0
  71. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +5 -6
  72. data/vendor/faiss/faiss/gpu/utils/Timer.h +2 -2
  73. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +5 -4
  74. data/vendor/faiss/faiss/impl/HNSW.cpp +2 -4
  75. data/vendor/faiss/faiss/impl/PolysemousTraining.h +4 -4
  76. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +22 -12
  77. data/vendor/faiss/faiss/impl/ProductQuantizer.h +2 -0
  78. data/vendor/faiss/faiss/impl/ResultHandler.h +452 -0
  79. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -19
  80. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +6 -0
  81. data/vendor/faiss/faiss/impl/index_read.cpp +64 -96
  82. data/vendor/faiss/faiss/impl/index_write.cpp +34 -25
  83. data/vendor/faiss/faiss/impl/io.cpp +33 -2
  84. data/vendor/faiss/faiss/impl/io.h +7 -2
  85. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -15
  86. data/vendor/faiss/faiss/impl/platform_macros.h +44 -0
  87. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +272 -0
  88. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +169 -0
  89. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +180 -0
  90. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +354 -0
  91. data/vendor/faiss/faiss/impl/simd_result_handlers.h +559 -0
  92. data/vendor/faiss/faiss/index_factory.cpp +112 -7
  93. data/vendor/faiss/faiss/index_io.h +1 -48
  94. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +151 -0
  95. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +76 -0
  96. data/vendor/faiss/faiss/{DirectMap.cpp → invlists/DirectMap.cpp} +1 -1
  97. data/vendor/faiss/faiss/{DirectMap.h → invlists/DirectMap.h} +1 -1
  98. data/vendor/faiss/faiss/{InvertedLists.cpp → invlists/InvertedLists.cpp} +72 -1
  99. data/vendor/faiss/faiss/{InvertedLists.h → invlists/InvertedLists.h} +32 -1
  100. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +107 -0
  101. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +63 -0
  102. data/vendor/faiss/faiss/{OnDiskInvertedLists.cpp → invlists/OnDiskInvertedLists.cpp} +21 -6
  103. data/vendor/faiss/faiss/{OnDiskInvertedLists.h → invlists/OnDiskInvertedLists.h} +5 -2
  104. data/vendor/faiss/faiss/python/python_callbacks.h +8 -1
  105. data/vendor/faiss/faiss/utils/AlignedTable.h +141 -0
  106. data/vendor/faiss/faiss/utils/Heap.cpp +2 -4
  107. data/vendor/faiss/faiss/utils/Heap.h +61 -50
  108. data/vendor/faiss/faiss/utils/distances.cpp +164 -319
  109. data/vendor/faiss/faiss/utils/distances.h +28 -20
  110. data/vendor/faiss/faiss/utils/distances_simd.cpp +277 -49
  111. data/vendor/faiss/faiss/utils/extra_distances.cpp +1 -2
  112. data/vendor/faiss/faiss/utils/hamming-inl.h +4 -4
  113. data/vendor/faiss/faiss/utils/hamming.cpp +3 -6
  114. data/vendor/faiss/faiss/utils/hamming.h +2 -7
  115. data/vendor/faiss/faiss/utils/ordered_key_value.h +98 -0
  116. data/vendor/faiss/faiss/utils/partitioning.cpp +1256 -0
  117. data/vendor/faiss/faiss/utils/partitioning.h +69 -0
  118. data/vendor/faiss/faiss/utils/quantize_lut.cpp +277 -0
  119. data/vendor/faiss/faiss/utils/quantize_lut.h +80 -0
  120. data/vendor/faiss/faiss/utils/simdlib.h +31 -0
  121. data/vendor/faiss/faiss/utils/simdlib_avx2.h +461 -0
  122. data/vendor/faiss/faiss/utils/simdlib_emulated.h +589 -0
  123. metadata +54 -149
  124. data/lib/faiss/index.rb +0 -20
  125. data/lib/faiss/index_binary.rb +0 -20
  126. data/lib/faiss/kmeans.rb +0 -15
  127. data/lib/faiss/pca_matrix.rb +0 -15
  128. data/lib/faiss/product_quantizer.rb +0 -22
  129. data/vendor/faiss/benchs/bench_6bit_codec.cpp +0 -80
  130. data/vendor/faiss/c_api/AutoTune_c.cpp +0 -83
  131. data/vendor/faiss/c_api/AutoTune_c.h +0 -66
  132. data/vendor/faiss/c_api/Clustering_c.cpp +0 -145
  133. data/vendor/faiss/c_api/Clustering_c.h +0 -123
  134. data/vendor/faiss/c_api/IndexFlat_c.cpp +0 -140
  135. data/vendor/faiss/c_api/IndexFlat_c.h +0 -115
  136. data/vendor/faiss/c_api/IndexIVFFlat_c.cpp +0 -64
  137. data/vendor/faiss/c_api/IndexIVFFlat_c.h +0 -58
  138. data/vendor/faiss/c_api/IndexIVF_c.cpp +0 -99
  139. data/vendor/faiss/c_api/IndexIVF_c.h +0 -142
  140. data/vendor/faiss/c_api/IndexLSH_c.cpp +0 -37
  141. data/vendor/faiss/c_api/IndexLSH_c.h +0 -40
  142. data/vendor/faiss/c_api/IndexPreTransform_c.cpp +0 -21
  143. data/vendor/faiss/c_api/IndexPreTransform_c.h +0 -32
  144. data/vendor/faiss/c_api/IndexShards_c.cpp +0 -38
  145. data/vendor/faiss/c_api/IndexShards_c.h +0 -39
  146. data/vendor/faiss/c_api/Index_c.cpp +0 -105
  147. data/vendor/faiss/c_api/Index_c.h +0 -183
  148. data/vendor/faiss/c_api/MetaIndexes_c.cpp +0 -49
  149. data/vendor/faiss/c_api/MetaIndexes_c.h +0 -49
  150. data/vendor/faiss/c_api/clone_index_c.cpp +0 -23
  151. data/vendor/faiss/c_api/clone_index_c.h +0 -32
  152. data/vendor/faiss/c_api/error_c.h +0 -42
  153. data/vendor/faiss/c_api/error_impl.cpp +0 -27
  154. data/vendor/faiss/c_api/error_impl.h +0 -16
  155. data/vendor/faiss/c_api/faiss_c.h +0 -58
  156. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +0 -98
  157. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.h +0 -56
  158. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +0 -52
  159. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.h +0 -68
  160. data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +0 -17
  161. data/vendor/faiss/c_api/gpu/GpuIndex_c.h +0 -30
  162. data/vendor/faiss/c_api/gpu/GpuIndicesOptions_c.h +0 -38
  163. data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +0 -86
  164. data/vendor/faiss/c_api/gpu/GpuResources_c.h +0 -66
  165. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +0 -54
  166. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.h +0 -53
  167. data/vendor/faiss/c_api/gpu/macros_impl.h +0 -42
  168. data/vendor/faiss/c_api/impl/AuxIndexStructures_c.cpp +0 -220
  169. data/vendor/faiss/c_api/impl/AuxIndexStructures_c.h +0 -149
  170. data/vendor/faiss/c_api/index_factory_c.cpp +0 -26
  171. data/vendor/faiss/c_api/index_factory_c.h +0 -30
  172. data/vendor/faiss/c_api/index_io_c.cpp +0 -42
  173. data/vendor/faiss/c_api/index_io_c.h +0 -50
  174. data/vendor/faiss/c_api/macros_impl.h +0 -110
  175. data/vendor/faiss/demos/demo_imi_flat.cpp +0 -154
  176. data/vendor/faiss/demos/demo_imi_pq.cpp +0 -203
  177. data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +0 -151
  178. data/vendor/faiss/demos/demo_sift1M.cpp +0 -252
  179. data/vendor/faiss/demos/demo_weighted_kmeans.cpp +0 -185
  180. data/vendor/faiss/misc/test_blas.cpp +0 -87
  181. data/vendor/faiss/tests/test_binary_flat.cpp +0 -62
  182. data/vendor/faiss/tests/test_dealloc_invlists.cpp +0 -188
  183. data/vendor/faiss/tests/test_ivfpq_codec.cpp +0 -70
  184. data/vendor/faiss/tests/test_ivfpq_indexing.cpp +0 -100
  185. data/vendor/faiss/tests/test_lowlevel_ivf.cpp +0 -573
  186. data/vendor/faiss/tests/test_merge.cpp +0 -260
  187. data/vendor/faiss/tests/test_omp_threads.cpp +0 -14
  188. data/vendor/faiss/tests/test_ondisk_ivf.cpp +0 -225
  189. data/vendor/faiss/tests/test_pairs_decoding.cpp +0 -193
  190. data/vendor/faiss/tests/test_params_override.cpp +0 -236
  191. data/vendor/faiss/tests/test_pq_encoding.cpp +0 -98
  192. data/vendor/faiss/tests/test_sliding_ivf.cpp +0 -246
  193. data/vendor/faiss/tests/test_threaded_index.cpp +0 -253
  194. data/vendor/faiss/tests/test_transfer_invlists.cpp +0 -159
  195. data/vendor/faiss/tutorial/cpp/1-Flat.cpp +0 -104
  196. data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +0 -85
  197. data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +0 -98
  198. data/vendor/faiss/tutorial/cpp/4-GPU.cpp +0 -122
  199. data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +0 -104
@@ -0,0 +1,180 @@
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/impl/pq4_fast_scan.h>
10
+
11
+ #include <faiss/impl/FaissAssert.h>
12
+ #include <faiss/impl/simd_result_handlers.h>
13
+
14
+
15
+ namespace faiss {
16
+
17
+
18
+ using namespace simd_result_handlers;
19
+
20
+ /***************************************************************
21
+ * accumulation functions
22
+ ***************************************************************/
23
+
24
+ namespace {
25
+
26
+ /*
27
+ * The computation kernel
28
+ * It accumulates results for NQ queries and BB * 32 database elements
29
+ * writes results in a ResultHandler
30
+ */
31
+
32
+ template<int NQ, int BB, class ResultHandler>
33
+ void kernel_accumulate_block(
34
+ int nsq,
35
+ const uint8_t *codes,
36
+ const uint8_t *LUT,
37
+ ResultHandler & res)
38
+ {
39
+ // distance accumulators
40
+ simd16uint16 accu[NQ][BB][4];
41
+
42
+ for(int q = 0; q < NQ; q++) {
43
+ for(int b = 0; b < BB; b++) {
44
+ accu[q][b][0].clear();
45
+ accu[q][b][1].clear();
46
+ accu[q][b][2].clear();
47
+ accu[q][b][3].clear();
48
+ }
49
+ }
50
+
51
+ for(int sq = 0; sq < nsq; sq += 2) {
52
+ simd32uint8 lut_cache[NQ];
53
+ for(int q = 0; q < NQ; q++) {
54
+ lut_cache[q] = simd32uint8(LUT);
55
+ LUT += 32;
56
+ }
57
+
58
+ for (int b = 0; b < BB; b++) {
59
+ simd32uint8 c = simd32uint8(codes);
60
+ codes += 32;
61
+ simd32uint8 mask(15);
62
+ simd32uint8 chi = simd32uint8(simd16uint16(c) >> 4) & mask;
63
+ simd32uint8 clo = c & mask;
64
+
65
+ for(int q = 0; q < NQ; q++) {
66
+ simd32uint8 lut = lut_cache[q];
67
+ simd32uint8 res0 = lut.lookup_2_lanes(clo);
68
+ simd32uint8 res1 = lut.lookup_2_lanes(chi);
69
+
70
+ accu[q][b][0] += simd16uint16(res0);
71
+ accu[q][b][1] += simd16uint16(res0) >> 8;
72
+
73
+ accu[q][b][2] += simd16uint16(res1);
74
+ accu[q][b][3] += simd16uint16(res1) >> 8;
75
+ }
76
+ }
77
+ }
78
+
79
+ for(int q = 0; q < NQ; q++) {
80
+ for (int b = 0; b < BB; b++) {
81
+
82
+ accu[q][b][0] -= accu[q][b][1] << 8;
83
+ simd16uint16 dis0 = combine2x2(accu[q][b][0], accu[q][b][1]);
84
+
85
+ accu[q][b][2] -= accu[q][b][3] << 8;
86
+ simd16uint16 dis1 = combine2x2(accu[q][b][2], accu[q][b][3]);
87
+
88
+ res.handle(q, b, dis0, dis1);
89
+ }
90
+ }
91
+
92
+
93
+ }
94
+
95
+
96
+ template<int NQ, int BB, class ResultHandler>
97
+ void accumulate_fixed_blocks(
98
+ size_t nb,
99
+ int nsq,
100
+ const uint8_t *codes,
101
+ const uint8_t *LUT,
102
+ ResultHandler & res)
103
+ {
104
+ constexpr int bbs = 32 * BB;
105
+ for (int64_t j0 = 0; j0 < nb; j0 += bbs) {
106
+ FixedStorageHandler<NQ, 2 * BB> res2;
107
+ kernel_accumulate_block<NQ, BB>(nsq, codes, LUT, res2);
108
+ res.set_block_origin(0, j0);
109
+ res2.to_other_handler(res);
110
+ codes += bbs * nsq / 2;
111
+ }
112
+ }
113
+
114
+
115
+ } // anonymous namespace
116
+
117
+ template<class ResultHandler>
118
+ void pq4_accumulate_loop(
119
+ int nq,
120
+ size_t nb, int bbs,
121
+ int nsq,
122
+ const uint8_t *codes,
123
+ const uint8_t *LUT,
124
+ ResultHandler & res)
125
+ {
126
+ FAISS_THROW_IF_NOT(is_aligned_pointer(codes));
127
+ FAISS_THROW_IF_NOT(is_aligned_pointer(LUT));
128
+ FAISS_THROW_IF_NOT(bbs % 32 == 0);
129
+ FAISS_THROW_IF_NOT(nb % bbs == 0);
130
+
131
+ #define DISPATCH(NQ, BB) \
132
+ case NQ * 1000 + BB: \
133
+ accumulate_fixed_blocks<NQ, BB>(nb, nsq, codes, LUT, res); \
134
+ break
135
+
136
+ switch(nq * 1000 + bbs / 32) {
137
+ DISPATCH(1, 1);
138
+ DISPATCH(1, 2);
139
+ DISPATCH(1, 3);
140
+ DISPATCH(1, 4);
141
+ DISPATCH(1, 5);
142
+ DISPATCH(2, 1);
143
+ DISPATCH(2, 2);
144
+ DISPATCH(3, 1);
145
+ DISPATCH(4, 1);
146
+ default:
147
+ FAISS_THROW_FMT("nq=%d bbs=%d not instantiated", nq, bbs);
148
+ }
149
+ #undef DISPATCH
150
+
151
+ }
152
+
153
+ // explicit template instantiations
154
+
155
+
156
+
157
+
158
+ #define INSTANTIATE_ACCUMULATE(TH, C, with_id_map) \
159
+ template void pq4_accumulate_loop<TH<C, with_id_map>> \
160
+ (int, size_t, int, int, const uint8_t *, const uint8_t *, TH<C, with_id_map> &);
161
+
162
+ #define INSTANTIATE_3(C, with_id_map) \
163
+ INSTANTIATE_ACCUMULATE(SingleResultHandler, C, with_id_map) \
164
+ INSTANTIATE_ACCUMULATE(HeapHandler, C, with_id_map) \
165
+ INSTANTIATE_ACCUMULATE(ReservoirHandler, C, with_id_map) \
166
+
167
+ using Csi = CMax<uint16_t, int>;
168
+ INSTANTIATE_3(Csi, false);
169
+ using CsiMin = CMin<uint16_t, int>;
170
+ INSTANTIATE_3(CsiMin, false);
171
+
172
+ using Csl = CMax<uint16_t, int64_t>;
173
+ INSTANTIATE_3(Csl, true);
174
+ using CslMin = CMin<uint16_t, int64_t>;
175
+ INSTANTIATE_3(CslMin, true);
176
+
177
+
178
+
179
+ } // namespace faiss
180
+
@@ -0,0 +1,354 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #include <faiss/impl/pq4_fast_scan.h>
9
+
10
+ #include <faiss/impl/FaissAssert.h>
11
+ #include <faiss/utils/simdlib.h>
12
+ #include <faiss/impl/simd_result_handlers.h>
13
+
14
+
15
+ namespace faiss {
16
+
17
+
18
+ using namespace simd_result_handlers;
19
+
20
+ /************************************************************
21
+ * Accumulation functions
22
+ ************************************************************/
23
+
24
+ namespace {
25
+
26
+ /*
27
+ * The computation kernel
28
+ * It accumulates results for NQ queries and 2 * 16 database elements
29
+ * writes results in a ResultHandler
30
+ */
31
+
32
+ template<int NQ, class ResultHandler>
33
+ void kernel_accumulate_block(
34
+ int nsq,
35
+ const uint8_t *codes,
36
+ const uint8_t *LUT,
37
+ ResultHandler & res)
38
+ {
39
+ // dummy alloc to keep the windows compiler happy
40
+ constexpr int NQA = NQ > 0 ? NQ : 1;
41
+ // distance accumulators
42
+ simd16uint16 accu[NQA][4];
43
+
44
+ for(int q = 0; q < NQ; q++) {
45
+ for(int b = 0; b < 4; b++) {
46
+ accu[q][b].clear();
47
+ }
48
+ }
49
+
50
+ // _mm_prefetch(codes + 768, 0);
51
+ for(int sq = 0; sq < nsq; sq += 2) {
52
+
53
+ // prefetch
54
+ simd32uint8 c(codes);
55
+ codes += 32;
56
+
57
+ simd32uint8 mask(0xf);
58
+ // shift op does not exist for int8...
59
+ simd32uint8 chi = simd32uint8(simd16uint16(c) >> 4) & mask;
60
+ simd32uint8 clo = c & mask;
61
+
62
+ for(int q = 0; q < NQ; q++) {
63
+ // load LUTs for 2 quantizers
64
+ simd32uint8 lut(LUT);
65
+ LUT += 32;
66
+
67
+ simd32uint8 res0 = lut.lookup_2_lanes(clo);
68
+ simd32uint8 res1 = lut.lookup_2_lanes(chi);
69
+
70
+ accu[q][0] += simd16uint16(res0);
71
+ accu[q][1] += simd16uint16(res0) >> 8;
72
+
73
+ accu[q][2] += simd16uint16(res1);
74
+ accu[q][3] += simd16uint16(res1) >> 8;
75
+ }
76
+ }
77
+
78
+ for(int q = 0; q < NQ; q++) {
79
+ accu[q][0] -= accu[q][1] << 8;
80
+ simd16uint16 dis0 = combine2x2(accu[q][0], accu[q][1]);
81
+ accu[q][2] -= accu[q][3] << 8;
82
+ simd16uint16 dis1 = combine2x2(accu[q][2], accu[q][3]);
83
+ res.handle(q, 0, dis0, dis1);
84
+ }
85
+
86
+ }
87
+
88
+ // handle at most 4 blocks of queries
89
+ template<int QBS, class ResultHandler>
90
+ void accumulate_q_4step(
91
+ size_t ntotal2,
92
+ int nsq,
93
+ const uint8_t *codes,
94
+ const uint8_t *LUT0,
95
+ ResultHandler & res)
96
+ {
97
+
98
+ constexpr int Q1 = QBS & 15;
99
+ constexpr int Q2 = (QBS >> 4) & 15;
100
+ constexpr int Q3 = (QBS >> 8) & 15;
101
+ constexpr int Q4 = (QBS >> 12) & 15;
102
+ constexpr int SQ = Q1 + Q2 + Q3 + Q4;
103
+
104
+ for (int64_t j0 = 0; j0 < ntotal2; j0 += 32) {
105
+ FixedStorageHandler<SQ, 2> res2;
106
+ const uint8_t *LUT = LUT0;
107
+ kernel_accumulate_block<Q1>(nsq, codes, LUT, res2);
108
+ LUT += Q1 * nsq * 16;
109
+ if (Q2 > 0) {
110
+ res2.set_block_origin(Q1, 0);
111
+ kernel_accumulate_block<Q2>(nsq, codes, LUT, res2);
112
+ LUT += Q2 * nsq * 16;
113
+ }
114
+ if (Q3 > 0) {
115
+ res2.set_block_origin(Q1 + Q2, 0);
116
+ kernel_accumulate_block<Q3>(nsq, codes, LUT, res2);
117
+ LUT += Q3 * nsq * 16;
118
+ }
119
+ if (Q4 > 0) {
120
+ res2.set_block_origin(Q1 + Q2 + Q3, 0);
121
+ kernel_accumulate_block<Q4>(nsq, codes, LUT, res2);
122
+ }
123
+ res.set_block_origin(0, j0);
124
+ res2.to_other_handler(res);
125
+ codes += 32 * nsq / 2;
126
+ }
127
+ }
128
+
129
+
130
+
131
+
132
+ template<int NQ, class ResultHandler>
133
+ void kernel_accumulate_block_loop(
134
+ size_t ntotal2,
135
+ int nsq,
136
+ const uint8_t *codes,
137
+ const uint8_t *LUT,
138
+ ResultHandler & res)
139
+ {
140
+
141
+ for (int64_t j0 = 0; j0 < ntotal2; j0 += 32) {
142
+ res.set_block_origin(0, j0);
143
+ kernel_accumulate_block<NQ, ResultHandler>
144
+ (nsq, codes + j0 * nsq / 2, LUT, res);
145
+ }
146
+
147
+ }
148
+
149
+ // non-template version of accumulate kernel -- dispatches dynamically
150
+ template<class ResultHandler>
151
+ void accumulate(
152
+ int nq,
153
+ size_t ntotal2,
154
+ int nsq,
155
+ const uint8_t *codes,
156
+ const uint8_t *LUT,
157
+ ResultHandler & res)
158
+ {
159
+
160
+ assert(nsq % 2 == 0);
161
+ assert(is_aligned_pointer(codes));
162
+ assert(is_aligned_pointer(LUT));
163
+
164
+ #define DISPATCH(NQ) \
165
+ case NQ: \
166
+ kernel_accumulate_block_loop<NQ, ResultHandler> \
167
+ (ntotal2, nsq, codes, LUT, res); \
168
+ return
169
+
170
+ switch(nq) {
171
+ DISPATCH(1);
172
+ DISPATCH(2);
173
+ DISPATCH(3);
174
+ DISPATCH(4);
175
+ }
176
+ FAISS_THROW_FMT("accumulate nq=%d not instanciated",
177
+ nq);
178
+
179
+ #undef DISPATCH
180
+ }
181
+
182
+
183
+ } // anonumous namespace
184
+
185
+
186
+
187
+ template<class ResultHandler>
188
+ void pq4_accumulate_loop_qbs(
189
+ int qbs,
190
+ size_t ntotal2,
191
+ int nsq,
192
+ const uint8_t *codes,
193
+ const uint8_t *LUT0,
194
+ ResultHandler & res)
195
+ {
196
+
197
+ assert(nsq % 2 == 0);
198
+ assert(is_aligned_pointer(codes));
199
+ assert(is_aligned_pointer(LUT0));
200
+
201
+ // try out optimized versions
202
+ switch(qbs) {
203
+ #define DISPATCH(QBS) \
204
+ case QBS: accumulate_q_4step<QBS> \
205
+ (ntotal2, nsq, codes, LUT0, res); \
206
+ return;
207
+ DISPATCH(0x3333); // 12
208
+ DISPATCH(0x2333); // 11
209
+ DISPATCH(0x2233); // 10
210
+ DISPATCH(0x333); // 9
211
+ DISPATCH(0x2223); // 9
212
+ DISPATCH(0x233); // 8
213
+ DISPATCH(0x1223); // 8
214
+ DISPATCH(0x223); // 7
215
+ DISPATCH(0x34); // 7
216
+ DISPATCH(0x133); // 7
217
+ DISPATCH(0x6); // 6
218
+ DISPATCH(0x33); // 6
219
+ DISPATCH(0x123); // 6
220
+ DISPATCH(0x222); // 6
221
+ DISPATCH(0x23); // 5
222
+ DISPATCH(0x5); // 5
223
+ DISPATCH(0x13); // 4
224
+ DISPATCH(0x22); // 4
225
+ DISPATCH(0x4); // 4
226
+ DISPATCH(0x3); // 3
227
+ DISPATCH(0x21); // 3
228
+ DISPATCH(0x2); // 2
229
+ DISPATCH(0x1); // 1
230
+ #undef DISPATCH
231
+ }
232
+
233
+ // default implementation where qbs is not known at compile time
234
+
235
+ for (int64_t j0 = 0; j0 < ntotal2; j0 += 32) {
236
+ const uint8_t *LUT = LUT0;
237
+ int qi = qbs;
238
+ int i0 = 0;
239
+ while(qi) {
240
+ int nq = qi & 15;
241
+ qi >>= 4;
242
+ res.set_block_origin(i0, j0);
243
+ #define DISPATCH(NQ) \
244
+ case NQ: \
245
+ kernel_accumulate_block<NQ, ResultHandler> \
246
+ (nsq, codes, LUT, res); \
247
+ break
248
+ switch(nq) {
249
+ DISPATCH(1);
250
+ DISPATCH(2);
251
+ DISPATCH(3);
252
+ DISPATCH(4);
253
+ #undef DISPATCH
254
+ default:
255
+ FAISS_THROW_FMT("accumulate nq=%d not instanciated",
256
+ nq);
257
+ }
258
+ i0 += nq;
259
+ LUT += nq * nsq * 16;
260
+ }
261
+ codes += 32 * nsq / 2;
262
+ }
263
+ }
264
+
265
+
266
+
267
+ // explicit template instantiations
268
+
269
+
270
+ #define INSTANTIATE_ACCUMULATE_Q(RH) \
271
+ template void pq4_accumulate_loop_qbs<RH> \
272
+ (int, size_t, int, const uint8_t *, const uint8_t *, RH &);
273
+
274
+ using Csi = CMax<uint16_t, int>;
275
+ INSTANTIATE_ACCUMULATE_Q(SingleResultHandler<Csi>)
276
+ INSTANTIATE_ACCUMULATE_Q(HeapHandler<Csi>)
277
+ INSTANTIATE_ACCUMULATE_Q(ReservoirHandler<Csi>)
278
+ using Csi2 = CMin<uint16_t, int>;
279
+ INSTANTIATE_ACCUMULATE_Q(SingleResultHandler<Csi2>)
280
+ INSTANTIATE_ACCUMULATE_Q(HeapHandler<Csi2>)
281
+ INSTANTIATE_ACCUMULATE_Q(ReservoirHandler<Csi2>)
282
+
283
+ using Cfl = CMax<uint16_t, int64_t>;
284
+ using HHCsl = HeapHandler<Cfl, true>;
285
+ using RHCsl = ReservoirHandler<Cfl, true>;
286
+ using SHCsl = SingleResultHandler<Cfl, true>;
287
+ INSTANTIATE_ACCUMULATE_Q(HHCsl)
288
+ INSTANTIATE_ACCUMULATE_Q(RHCsl)
289
+ INSTANTIATE_ACCUMULATE_Q(SHCsl)
290
+ using Cfl2 = CMin<uint16_t, int64_t>;
291
+ using HHCsl2 = HeapHandler<Cfl2, true>;
292
+ using RHCsl2 = ReservoirHandler<Cfl2, true>;
293
+ using SHCsl2 = SingleResultHandler<Cfl2, true>;
294
+ INSTANTIATE_ACCUMULATE_Q(HHCsl2)
295
+ INSTANTIATE_ACCUMULATE_Q(RHCsl2)
296
+ INSTANTIATE_ACCUMULATE_Q(SHCsl2)
297
+
298
+
299
+ /***************************************************************
300
+ * Packing functions
301
+ ***************************************************************/
302
+
303
+ int pq4_qbs_to_nq(int qbs) {
304
+ int i0 = 0;
305
+ int qi = qbs;
306
+ while(qi) {
307
+ int nq = qi & 15;
308
+ qi >>= 4;
309
+ i0 += nq;
310
+ }
311
+ return i0;
312
+ }
313
+
314
+
315
+
316
+ void accumulate_to_mem(
317
+ int nq,
318
+ size_t ntotal2,
319
+ int nsq,
320
+ const uint8_t *codes,
321
+ const uint8_t *LUT,
322
+ uint16_t* accu)
323
+ {
324
+ FAISS_THROW_IF_NOT(ntotal2 % 32 == 0);
325
+ StoreResultHandler handler(accu, ntotal2);
326
+ accumulate(nq, ntotal2, nsq, codes, LUT, handler);
327
+ }
328
+
329
+
330
+ int pq4_preferred_qbs(int n) {
331
+ // from timmings in P141901742, P141902828
332
+ static int map[12] = {
333
+ 0, 1, 2, 3, 0x13,
334
+ 0x23, 0x33, 0x223, 0x233, 0x333,
335
+ 0x2233, 0x2333
336
+ };
337
+ if (n <= 11) {
338
+ return map[n];
339
+ } else if (n <= 24) {
340
+ // override qbs: all first stages with 3 steps
341
+ // then 1 stage with the rest
342
+ int nbit = 4 * (n / 3); // nbits with only 3s
343
+ int qbs = 0x33333333 & ((1 << nbit) - 1);
344
+ qbs |= (n % 3) << nbit;
345
+ return qbs;
346
+ } else {
347
+ FAISS_THROW_FMT("number of queries %d too large", n);
348
+ }
349
+ }
350
+
351
+
352
+
353
+ } // namespace faiss
354
+