faiss 0.1.3 → 0.1.4

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 (184) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/ext/faiss/extconf.rb +1 -1
  6. data/lib/faiss/version.rb +1 -1
  7. data/vendor/faiss/faiss/AutoTune.cpp +36 -33
  8. data/vendor/faiss/faiss/AutoTune.h +6 -3
  9. data/vendor/faiss/faiss/Clustering.cpp +16 -12
  10. data/vendor/faiss/faiss/Index.cpp +3 -4
  11. data/vendor/faiss/faiss/Index.h +3 -3
  12. data/vendor/faiss/faiss/IndexBinary.cpp +3 -4
  13. data/vendor/faiss/faiss/IndexBinary.h +1 -1
  14. data/vendor/faiss/faiss/IndexBinaryHash.cpp +2 -12
  15. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +1 -2
  16. data/vendor/faiss/faiss/IndexFlat.cpp +0 -148
  17. data/vendor/faiss/faiss/IndexFlat.h +0 -51
  18. data/vendor/faiss/faiss/IndexHNSW.cpp +4 -5
  19. data/vendor/faiss/faiss/IndexIVF.cpp +118 -31
  20. data/vendor/faiss/faiss/IndexIVF.h +22 -15
  21. data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -3
  22. data/vendor/faiss/faiss/IndexIVFFlat.h +2 -1
  23. data/vendor/faiss/faiss/IndexIVFPQ.cpp +39 -15
  24. data/vendor/faiss/faiss/IndexIVFPQ.h +25 -9
  25. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1116 -0
  26. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +166 -0
  27. data/vendor/faiss/faiss/IndexIVFPQR.cpp +8 -9
  28. data/vendor/faiss/faiss/IndexIVFPQR.h +2 -1
  29. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +1 -2
  30. data/vendor/faiss/faiss/IndexPQ.cpp +34 -18
  31. data/vendor/faiss/faiss/IndexPQFastScan.cpp +536 -0
  32. data/vendor/faiss/faiss/IndexPQFastScan.h +111 -0
  33. data/vendor/faiss/faiss/IndexPreTransform.cpp +47 -0
  34. data/vendor/faiss/faiss/IndexPreTransform.h +2 -0
  35. data/vendor/faiss/faiss/IndexRefine.cpp +256 -0
  36. data/vendor/faiss/faiss/IndexRefine.h +73 -0
  37. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +2 -2
  38. data/vendor/faiss/faiss/IndexScalarQuantizer.h +1 -1
  39. data/vendor/faiss/faiss/gpu/GpuDistance.h +1 -1
  40. data/vendor/faiss/faiss/gpu/GpuIndex.h +16 -9
  41. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +8 -1
  42. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -11
  43. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +19 -2
  44. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +28 -2
  45. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +24 -14
  46. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +29 -2
  47. data/vendor/faiss/faiss/gpu/GpuResources.h +4 -0
  48. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +60 -27
  49. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +28 -6
  50. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +547 -0
  51. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +51 -0
  52. data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +3 -3
  53. data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +3 -2
  54. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +274 -0
  55. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +7 -2
  56. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +5 -1
  57. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +231 -0
  58. data/vendor/faiss/faiss/gpu/test/TestUtils.h +33 -0
  59. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -0
  60. data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +6 -0
  61. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +5 -6
  62. data/vendor/faiss/faiss/gpu/utils/Timer.h +2 -2
  63. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +5 -4
  64. data/vendor/faiss/faiss/impl/HNSW.cpp +2 -4
  65. data/vendor/faiss/faiss/impl/PolysemousTraining.h +4 -4
  66. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +22 -12
  67. data/vendor/faiss/faiss/impl/ProductQuantizer.h +2 -0
  68. data/vendor/faiss/faiss/impl/ResultHandler.h +452 -0
  69. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -19
  70. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +6 -0
  71. data/vendor/faiss/faiss/impl/index_read.cpp +64 -96
  72. data/vendor/faiss/faiss/impl/index_write.cpp +34 -25
  73. data/vendor/faiss/faiss/impl/io.cpp +33 -2
  74. data/vendor/faiss/faiss/impl/io.h +7 -2
  75. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -15
  76. data/vendor/faiss/faiss/impl/platform_macros.h +44 -0
  77. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +272 -0
  78. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +169 -0
  79. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +180 -0
  80. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +354 -0
  81. data/vendor/faiss/faiss/impl/simd_result_handlers.h +559 -0
  82. data/vendor/faiss/faiss/index_factory.cpp +112 -7
  83. data/vendor/faiss/faiss/index_io.h +1 -48
  84. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +151 -0
  85. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +76 -0
  86. data/vendor/faiss/faiss/{DirectMap.cpp → invlists/DirectMap.cpp} +1 -1
  87. data/vendor/faiss/faiss/{DirectMap.h → invlists/DirectMap.h} +1 -1
  88. data/vendor/faiss/faiss/{InvertedLists.cpp → invlists/InvertedLists.cpp} +72 -1
  89. data/vendor/faiss/faiss/{InvertedLists.h → invlists/InvertedLists.h} +32 -1
  90. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +107 -0
  91. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +63 -0
  92. data/vendor/faiss/faiss/{OnDiskInvertedLists.cpp → invlists/OnDiskInvertedLists.cpp} +21 -6
  93. data/vendor/faiss/faiss/{OnDiskInvertedLists.h → invlists/OnDiskInvertedLists.h} +5 -2
  94. data/vendor/faiss/faiss/python/python_callbacks.h +8 -1
  95. data/vendor/faiss/faiss/utils/AlignedTable.h +141 -0
  96. data/vendor/faiss/faiss/utils/Heap.cpp +2 -4
  97. data/vendor/faiss/faiss/utils/Heap.h +61 -50
  98. data/vendor/faiss/faiss/utils/distances.cpp +164 -319
  99. data/vendor/faiss/faiss/utils/distances.h +28 -20
  100. data/vendor/faiss/faiss/utils/distances_simd.cpp +277 -49
  101. data/vendor/faiss/faiss/utils/extra_distances.cpp +1 -2
  102. data/vendor/faiss/faiss/utils/hamming-inl.h +4 -4
  103. data/vendor/faiss/faiss/utils/hamming.cpp +3 -6
  104. data/vendor/faiss/faiss/utils/hamming.h +2 -7
  105. data/vendor/faiss/faiss/utils/ordered_key_value.h +98 -0
  106. data/vendor/faiss/faiss/utils/partitioning.cpp +1256 -0
  107. data/vendor/faiss/faiss/utils/partitioning.h +69 -0
  108. data/vendor/faiss/faiss/utils/quantize_lut.cpp +277 -0
  109. data/vendor/faiss/faiss/utils/quantize_lut.h +80 -0
  110. data/vendor/faiss/faiss/utils/simdlib.h +31 -0
  111. data/vendor/faiss/faiss/utils/simdlib_avx2.h +461 -0
  112. data/vendor/faiss/faiss/utils/simdlib_emulated.h +589 -0
  113. metadata +43 -141
  114. data/vendor/faiss/benchs/bench_6bit_codec.cpp +0 -80
  115. data/vendor/faiss/c_api/AutoTune_c.cpp +0 -83
  116. data/vendor/faiss/c_api/AutoTune_c.h +0 -66
  117. data/vendor/faiss/c_api/Clustering_c.cpp +0 -145
  118. data/vendor/faiss/c_api/Clustering_c.h +0 -123
  119. data/vendor/faiss/c_api/IndexFlat_c.cpp +0 -140
  120. data/vendor/faiss/c_api/IndexFlat_c.h +0 -115
  121. data/vendor/faiss/c_api/IndexIVFFlat_c.cpp +0 -64
  122. data/vendor/faiss/c_api/IndexIVFFlat_c.h +0 -58
  123. data/vendor/faiss/c_api/IndexIVF_c.cpp +0 -99
  124. data/vendor/faiss/c_api/IndexIVF_c.h +0 -142
  125. data/vendor/faiss/c_api/IndexLSH_c.cpp +0 -37
  126. data/vendor/faiss/c_api/IndexLSH_c.h +0 -40
  127. data/vendor/faiss/c_api/IndexPreTransform_c.cpp +0 -21
  128. data/vendor/faiss/c_api/IndexPreTransform_c.h +0 -32
  129. data/vendor/faiss/c_api/IndexShards_c.cpp +0 -38
  130. data/vendor/faiss/c_api/IndexShards_c.h +0 -39
  131. data/vendor/faiss/c_api/Index_c.cpp +0 -105
  132. data/vendor/faiss/c_api/Index_c.h +0 -183
  133. data/vendor/faiss/c_api/MetaIndexes_c.cpp +0 -49
  134. data/vendor/faiss/c_api/MetaIndexes_c.h +0 -49
  135. data/vendor/faiss/c_api/clone_index_c.cpp +0 -23
  136. data/vendor/faiss/c_api/clone_index_c.h +0 -32
  137. data/vendor/faiss/c_api/error_c.h +0 -42
  138. data/vendor/faiss/c_api/error_impl.cpp +0 -27
  139. data/vendor/faiss/c_api/error_impl.h +0 -16
  140. data/vendor/faiss/c_api/faiss_c.h +0 -58
  141. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +0 -98
  142. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.h +0 -56
  143. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +0 -52
  144. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.h +0 -68
  145. data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +0 -17
  146. data/vendor/faiss/c_api/gpu/GpuIndex_c.h +0 -30
  147. data/vendor/faiss/c_api/gpu/GpuIndicesOptions_c.h +0 -38
  148. data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +0 -86
  149. data/vendor/faiss/c_api/gpu/GpuResources_c.h +0 -66
  150. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +0 -54
  151. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.h +0 -53
  152. data/vendor/faiss/c_api/gpu/macros_impl.h +0 -42
  153. data/vendor/faiss/c_api/impl/AuxIndexStructures_c.cpp +0 -220
  154. data/vendor/faiss/c_api/impl/AuxIndexStructures_c.h +0 -149
  155. data/vendor/faiss/c_api/index_factory_c.cpp +0 -26
  156. data/vendor/faiss/c_api/index_factory_c.h +0 -30
  157. data/vendor/faiss/c_api/index_io_c.cpp +0 -42
  158. data/vendor/faiss/c_api/index_io_c.h +0 -50
  159. data/vendor/faiss/c_api/macros_impl.h +0 -110
  160. data/vendor/faiss/demos/demo_imi_flat.cpp +0 -154
  161. data/vendor/faiss/demos/demo_imi_pq.cpp +0 -203
  162. data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +0 -151
  163. data/vendor/faiss/demos/demo_sift1M.cpp +0 -252
  164. data/vendor/faiss/demos/demo_weighted_kmeans.cpp +0 -185
  165. data/vendor/faiss/misc/test_blas.cpp +0 -87
  166. data/vendor/faiss/tests/test_binary_flat.cpp +0 -62
  167. data/vendor/faiss/tests/test_dealloc_invlists.cpp +0 -188
  168. data/vendor/faiss/tests/test_ivfpq_codec.cpp +0 -70
  169. data/vendor/faiss/tests/test_ivfpq_indexing.cpp +0 -100
  170. data/vendor/faiss/tests/test_lowlevel_ivf.cpp +0 -573
  171. data/vendor/faiss/tests/test_merge.cpp +0 -260
  172. data/vendor/faiss/tests/test_omp_threads.cpp +0 -14
  173. data/vendor/faiss/tests/test_ondisk_ivf.cpp +0 -225
  174. data/vendor/faiss/tests/test_pairs_decoding.cpp +0 -193
  175. data/vendor/faiss/tests/test_params_override.cpp +0 -236
  176. data/vendor/faiss/tests/test_pq_encoding.cpp +0 -98
  177. data/vendor/faiss/tests/test_sliding_ivf.cpp +0 -246
  178. data/vendor/faiss/tests/test_threaded_index.cpp +0 -253
  179. data/vendor/faiss/tests/test_transfer_invlists.cpp +0 -159
  180. data/vendor/faiss/tutorial/cpp/1-Flat.cpp +0 -104
  181. data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +0 -85
  182. data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +0 -98
  183. data/vendor/faiss/tutorial/cpp/4-GPU.cpp +0 -122
  184. 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
+