faiss 0.3.0 → 0.3.2

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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/ext/faiss/extconf.rb +9 -2
  6. data/ext/faiss/index.cpp +1 -1
  7. data/ext/faiss/index_binary.cpp +2 -2
  8. data/ext/faiss/product_quantizer.cpp +1 -1
  9. data/lib/faiss/version.rb +1 -1
  10. data/vendor/faiss/faiss/AutoTune.cpp +7 -7
  11. data/vendor/faiss/faiss/AutoTune.h +1 -2
  12. data/vendor/faiss/faiss/Clustering.cpp +39 -22
  13. data/vendor/faiss/faiss/Clustering.h +40 -21
  14. data/vendor/faiss/faiss/IVFlib.cpp +26 -12
  15. data/vendor/faiss/faiss/Index.cpp +1 -1
  16. data/vendor/faiss/faiss/Index.h +40 -10
  17. data/vendor/faiss/faiss/Index2Layer.cpp +7 -7
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +176 -166
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +15 -15
  20. data/vendor/faiss/faiss/IndexBinary.cpp +9 -4
  21. data/vendor/faiss/faiss/IndexBinary.h +8 -19
  22. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +2 -1
  23. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +24 -31
  24. data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
  25. data/vendor/faiss/faiss/IndexBinaryHash.cpp +25 -50
  26. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +107 -188
  27. data/vendor/faiss/faiss/IndexFastScan.cpp +95 -146
  28. data/vendor/faiss/faiss/IndexFastScan.h +9 -8
  29. data/vendor/faiss/faiss/IndexFlat.cpp +206 -10
  30. data/vendor/faiss/faiss/IndexFlat.h +20 -1
  31. data/vendor/faiss/faiss/IndexFlatCodes.cpp +170 -5
  32. data/vendor/faiss/faiss/IndexFlatCodes.h +23 -4
  33. data/vendor/faiss/faiss/IndexHNSW.cpp +231 -382
  34. data/vendor/faiss/faiss/IndexHNSW.h +62 -49
  35. data/vendor/faiss/faiss/IndexIDMap.cpp +69 -28
  36. data/vendor/faiss/faiss/IndexIDMap.h +24 -2
  37. data/vendor/faiss/faiss/IndexIVF.cpp +162 -56
  38. data/vendor/faiss/faiss/IndexIVF.h +46 -6
  39. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +33 -26
  40. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +6 -2
  41. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +19 -46
  42. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -3
  43. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +502 -401
  44. data/vendor/faiss/faiss/IndexIVFFastScan.h +63 -26
  45. data/vendor/faiss/faiss/IndexIVFFlat.cpp +15 -5
  46. data/vendor/faiss/faiss/IndexIVFFlat.h +3 -2
  47. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +172 -0
  48. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.h +56 -0
  49. data/vendor/faiss/faiss/IndexIVFPQ.cpp +79 -125
  50. data/vendor/faiss/faiss/IndexIVFPQ.h +6 -7
  51. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +39 -52
  52. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +4 -3
  53. data/vendor/faiss/faiss/IndexIVFPQR.cpp +45 -29
  54. data/vendor/faiss/faiss/IndexIVFPQR.h +5 -2
  55. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +25 -27
  56. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +6 -6
  57. data/vendor/faiss/faiss/IndexLSH.cpp +14 -16
  58. data/vendor/faiss/faiss/IndexLattice.cpp +1 -19
  59. data/vendor/faiss/faiss/IndexLattice.h +3 -22
  60. data/vendor/faiss/faiss/IndexNNDescent.cpp +3 -33
  61. data/vendor/faiss/faiss/IndexNNDescent.h +1 -1
  62. data/vendor/faiss/faiss/IndexNSG.cpp +11 -27
  63. data/vendor/faiss/faiss/IndexNSG.h +11 -11
  64. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
  65. data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
  66. data/vendor/faiss/faiss/IndexPQ.cpp +72 -88
  67. data/vendor/faiss/faiss/IndexPQ.h +1 -4
  68. data/vendor/faiss/faiss/IndexPQFastScan.cpp +1 -1
  69. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -31
  70. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  71. data/vendor/faiss/faiss/IndexRefine.cpp +54 -24
  72. data/vendor/faiss/faiss/IndexRefine.h +7 -0
  73. data/vendor/faiss/faiss/IndexReplicas.cpp +23 -26
  74. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +25 -17
  75. data/vendor/faiss/faiss/IndexScalarQuantizer.h +6 -4
  76. data/vendor/faiss/faiss/IndexShards.cpp +21 -29
  77. data/vendor/faiss/faiss/IndexShardsIVF.cpp +1 -2
  78. data/vendor/faiss/faiss/MatrixStats.cpp +17 -32
  79. data/vendor/faiss/faiss/MatrixStats.h +21 -9
  80. data/vendor/faiss/faiss/MetaIndexes.cpp +35 -35
  81. data/vendor/faiss/faiss/MetricType.h +7 -2
  82. data/vendor/faiss/faiss/VectorTransform.cpp +13 -26
  83. data/vendor/faiss/faiss/VectorTransform.h +7 -7
  84. data/vendor/faiss/faiss/clone_index.cpp +15 -10
  85. data/vendor/faiss/faiss/clone_index.h +3 -0
  86. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +95 -17
  87. data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +152 -0
  88. data/vendor/faiss/faiss/cppcontrib/factory_tools.h +24 -0
  89. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +83 -30
  90. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +123 -8
  91. data/vendor/faiss/faiss/gpu/GpuCloner.h +22 -0
  92. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +13 -0
  93. data/vendor/faiss/faiss/gpu/GpuDistance.h +46 -38
  94. data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -1
  95. data/vendor/faiss/faiss/gpu/GpuIndex.h +30 -12
  96. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +282 -0
  97. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +4 -4
  98. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +14 -9
  99. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +20 -3
  100. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -11
  101. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +1 -3
  102. data/vendor/faiss/faiss/gpu/GpuResources.cpp +24 -3
  103. data/vendor/faiss/faiss/gpu/GpuResources.h +39 -11
  104. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +142 -17
  105. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +57 -3
  106. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +26 -21
  107. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +7 -1
  108. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +8 -5
  109. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +25 -0
  110. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +129 -9
  111. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +332 -40
  112. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +299 -208
  113. data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +1 -0
  114. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
  115. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
  116. data/vendor/faiss/faiss/gpu/utils/RaftUtils.h +75 -0
  117. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +4 -1
  118. data/vendor/faiss/faiss/gpu/utils/Timer.h +1 -1
  119. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +3 -1
  120. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +5 -5
  121. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +26 -1
  122. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +10 -3
  123. data/vendor/faiss/faiss/impl/DistanceComputer.h +70 -1
  124. data/vendor/faiss/faiss/impl/FaissAssert.h +4 -2
  125. data/vendor/faiss/faiss/impl/FaissException.h +13 -34
  126. data/vendor/faiss/faiss/impl/HNSW.cpp +605 -186
  127. data/vendor/faiss/faiss/impl/HNSW.h +52 -30
  128. data/vendor/faiss/faiss/impl/IDSelector.h +4 -4
  129. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +11 -9
  130. data/vendor/faiss/faiss/impl/LookupTableScaler.h +34 -0
  131. data/vendor/faiss/faiss/impl/NNDescent.cpp +42 -27
  132. data/vendor/faiss/faiss/impl/NSG.cpp +0 -29
  133. data/vendor/faiss/faiss/impl/NSG.h +1 -1
  134. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +14 -12
  135. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +1 -1
  136. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +25 -22
  137. data/vendor/faiss/faiss/impl/ProductQuantizer.h +6 -2
  138. data/vendor/faiss/faiss/impl/Quantizer.h +1 -1
  139. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +27 -1015
  140. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +5 -63
  141. data/vendor/faiss/faiss/impl/ResultHandler.h +347 -172
  142. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +1104 -147
  143. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +3 -8
  144. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +285 -42
  145. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
  146. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +21 -14
  147. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +22 -12
  148. data/vendor/faiss/faiss/impl/index_read.cpp +74 -34
  149. data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
  150. data/vendor/faiss/faiss/impl/index_write.cpp +88 -51
  151. data/vendor/faiss/faiss/impl/io.cpp +23 -15
  152. data/vendor/faiss/faiss/impl/io.h +4 -4
  153. data/vendor/faiss/faiss/impl/io_macros.h +6 -0
  154. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
  155. data/vendor/faiss/faiss/impl/platform_macros.h +40 -1
  156. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +14 -0
  157. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +7 -6
  158. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +52 -38
  159. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +487 -49
  160. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +960 -0
  161. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +176 -0
  162. data/vendor/faiss/faiss/impl/simd_result_handlers.h +481 -225
  163. data/vendor/faiss/faiss/index_factory.cpp +41 -20
  164. data/vendor/faiss/faiss/index_io.h +12 -5
  165. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +28 -8
  166. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +3 -0
  167. data/vendor/faiss/faiss/invlists/DirectMap.cpp +10 -2
  168. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +73 -17
  169. data/vendor/faiss/faiss/invlists/InvertedLists.h +26 -8
  170. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +24 -9
  171. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +2 -1
  172. data/vendor/faiss/faiss/python/python_callbacks.cpp +4 -4
  173. data/vendor/faiss/faiss/utils/Heap.cpp +3 -1
  174. data/vendor/faiss/faiss/utils/Heap.h +105 -0
  175. data/vendor/faiss/faiss/utils/NeuralNet.cpp +342 -0
  176. data/vendor/faiss/faiss/utils/NeuralNet.h +147 -0
  177. data/vendor/faiss/faiss/utils/WorkerThread.h +1 -0
  178. data/vendor/faiss/faiss/utils/bf16.h +36 -0
  179. data/vendor/faiss/faiss/utils/distances.cpp +147 -123
  180. data/vendor/faiss/faiss/utils/distances.h +86 -9
  181. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +5 -5
  182. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +2 -2
  183. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +2 -2
  184. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +1 -1
  185. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +5 -5
  186. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +1 -1
  187. data/vendor/faiss/faiss/utils/distances_simd.cpp +1589 -243
  188. data/vendor/faiss/faiss/utils/extra_distances-inl.h +70 -0
  189. data/vendor/faiss/faiss/utils/extra_distances.cpp +85 -137
  190. data/vendor/faiss/faiss/utils/extra_distances.h +3 -2
  191. data/vendor/faiss/faiss/utils/fp16-arm.h +29 -0
  192. data/vendor/faiss/faiss/utils/fp16.h +2 -0
  193. data/vendor/faiss/faiss/utils/hamming.cpp +163 -111
  194. data/vendor/faiss/faiss/utils/hamming.h +58 -0
  195. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +16 -89
  196. data/vendor/faiss/faiss/utils/hamming_distance/common.h +1 -0
  197. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +19 -88
  198. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +58 -0
  199. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +14 -104
  200. data/vendor/faiss/faiss/utils/partitioning.cpp +3 -4
  201. data/vendor/faiss/faiss/utils/prefetch.h +77 -0
  202. data/vendor/faiss/faiss/utils/quantize_lut.cpp +0 -14
  203. data/vendor/faiss/faiss/utils/random.cpp +43 -0
  204. data/vendor/faiss/faiss/utils/random.h +25 -0
  205. data/vendor/faiss/faiss/utils/simdlib.h +10 -1
  206. data/vendor/faiss/faiss/utils/simdlib_avx2.h +0 -6
  207. data/vendor/faiss/faiss/utils/simdlib_avx512.h +296 -0
  208. data/vendor/faiss/faiss/utils/simdlib_neon.h +77 -79
  209. data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
  210. data/vendor/faiss/faiss/utils/sorting.cpp +140 -5
  211. data/vendor/faiss/faiss/utils/sorting.h +27 -0
  212. data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
  213. data/vendor/faiss/faiss/utils/utils.cpp +120 -7
  214. data/vendor/faiss/faiss/utils/utils.h +60 -20
  215. metadata +23 -4
  216. data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +0 -102
@@ -0,0 +1,248 @@
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
+ #pragma once
9
+
10
+ #ifdef __AVX512F__
11
+
12
+ #include <immintrin.h>
13
+
14
+ #include <type_traits>
15
+
16
+ #include <faiss/impl/ProductQuantizer.h>
17
+ #include <faiss/impl/code_distance/code_distance-generic.h>
18
+
19
+ namespace faiss {
20
+
21
+ // According to experiments, the AVX-512 version may be SLOWER than
22
+ // the AVX2 version, which is somewhat unexpected.
23
+ // This version is not used for now, but it may be used later.
24
+ //
25
+ // TODO: test for AMD CPUs.
26
+
27
+ template <typename PQDecoderT>
28
+ typename std::enable_if<!std::is_same<PQDecoderT, PQDecoder8>::value, float>::
29
+ type inline distance_single_code_avx512(
30
+ // number of subquantizers
31
+ const size_t M,
32
+ // number of bits per quantization index
33
+ const size_t nbits,
34
+ // precomputed distances, layout (M, ksub)
35
+ const float* sim_table,
36
+ const uint8_t* code) {
37
+ // default implementation
38
+ return distance_single_code_generic<PQDecoderT>(M, nbits, sim_table, code);
39
+ }
40
+
41
+ template <typename PQDecoderT>
42
+ typename std::enable_if<std::is_same<PQDecoderT, PQDecoder8>::value, float>::
43
+ type inline distance_single_code_avx512(
44
+ // number of subquantizers
45
+ const size_t M,
46
+ // number of bits per quantization index
47
+ const size_t nbits,
48
+ // precomputed distances, layout (M, ksub)
49
+ const float* sim_table,
50
+ const uint8_t* code0) {
51
+ float result0 = 0;
52
+ constexpr size_t ksub = 1 << 8;
53
+
54
+ size_t m = 0;
55
+ const size_t pqM16 = M / 16;
56
+
57
+ constexpr intptr_t N = 1;
58
+
59
+ const float* tab = sim_table;
60
+
61
+ if (pqM16 > 0) {
62
+ // process 16 values per loop
63
+ const __m512i vksub = _mm512_set1_epi32(ksub);
64
+ __m512i offsets_0 = _mm512_setr_epi32(
65
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
66
+ offsets_0 = _mm512_mullo_epi32(offsets_0, vksub);
67
+
68
+ // accumulators of partial sums
69
+ __m512 partialSums[N];
70
+ for (intptr_t j = 0; j < N; j++) {
71
+ partialSums[j] = _mm512_setzero_ps();
72
+ }
73
+
74
+ // loop
75
+ for (m = 0; m < pqM16 * 16; m += 16) {
76
+ // load 16 uint8 values
77
+ __m128i mm1[N];
78
+ mm1[0] = _mm_loadu_si128((const __m128i_u*)(code0 + m));
79
+
80
+ // process first 8 codes
81
+ for (intptr_t j = 0; j < N; j++) {
82
+ const __m512i idx1 = _mm512_cvtepu8_epi32(mm1[j]);
83
+
84
+ // add offsets
85
+ const __m512i indices_to_read_from =
86
+ _mm512_add_epi32(idx1, offsets_0);
87
+
88
+ // gather 16 values, similar to 16 operations of tab[idx]
89
+ __m512 collected = _mm512_i32gather_ps(
90
+ indices_to_read_from, tab, sizeof(float));
91
+
92
+ // collect partial sums
93
+ partialSums[j] = _mm512_add_ps(partialSums[j], collected);
94
+ }
95
+ tab += ksub * 16;
96
+ }
97
+
98
+ // horizontal sum for partialSum
99
+ result0 += _mm512_reduce_add_ps(partialSums[0]);
100
+ }
101
+
102
+ //
103
+ if (m < M) {
104
+ // process leftovers
105
+ PQDecoder8 decoder0(code0 + m, nbits);
106
+ for (; m < M; m++) {
107
+ result0 += tab[decoder0.decode()];
108
+ tab += ksub;
109
+ }
110
+ }
111
+
112
+ return result0;
113
+ }
114
+
115
+ template <typename PQDecoderT>
116
+ typename std::enable_if<!std::is_same<PQDecoderT, PQDecoder8>::value, void>::
117
+ type
118
+ distance_four_codes_avx512(
119
+ // number of subquantizers
120
+ const size_t M,
121
+ // number of bits per quantization index
122
+ const size_t nbits,
123
+ // precomputed distances, layout (M, ksub)
124
+ const float* sim_table,
125
+ // codes
126
+ const uint8_t* __restrict code0,
127
+ const uint8_t* __restrict code1,
128
+ const uint8_t* __restrict code2,
129
+ const uint8_t* __restrict code3,
130
+ // computed distances
131
+ float& result0,
132
+ float& result1,
133
+ float& result2,
134
+ float& result3) {
135
+ distance_four_codes_generic<PQDecoderT>(
136
+ M,
137
+ nbits,
138
+ sim_table,
139
+ code0,
140
+ code1,
141
+ code2,
142
+ code3,
143
+ result0,
144
+ result1,
145
+ result2,
146
+ result3);
147
+ }
148
+
149
+ // Combines 4 operations of distance_single_code()
150
+ template <typename PQDecoderT>
151
+ typename std::enable_if<std::is_same<PQDecoderT, PQDecoder8>::value, void>::type
152
+ distance_four_codes_avx512(
153
+ // number of subquantizers
154
+ const size_t M,
155
+ // number of bits per quantization index
156
+ const size_t nbits,
157
+ // precomputed distances, layout (M, ksub)
158
+ const float* sim_table,
159
+ // codes
160
+ const uint8_t* __restrict code0,
161
+ const uint8_t* __restrict code1,
162
+ const uint8_t* __restrict code2,
163
+ const uint8_t* __restrict code3,
164
+ // computed distances
165
+ float& result0,
166
+ float& result1,
167
+ float& result2,
168
+ float& result3) {
169
+ result0 = 0;
170
+ result1 = 0;
171
+ result2 = 0;
172
+ result3 = 0;
173
+ constexpr size_t ksub = 1 << 8;
174
+
175
+ size_t m = 0;
176
+ const size_t pqM16 = M / 16;
177
+
178
+ constexpr intptr_t N = 4;
179
+
180
+ const float* tab = sim_table;
181
+
182
+ if (pqM16 > 0) {
183
+ // process 16 values per loop
184
+ const __m512i vksub = _mm512_set1_epi32(ksub);
185
+ __m512i offsets_0 = _mm512_setr_epi32(
186
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
187
+ offsets_0 = _mm512_mullo_epi32(offsets_0, vksub);
188
+
189
+ // accumulators of partial sums
190
+ __m512 partialSums[N];
191
+ for (intptr_t j = 0; j < N; j++) {
192
+ partialSums[j] = _mm512_setzero_ps();
193
+ }
194
+
195
+ // loop
196
+ for (m = 0; m < pqM16 * 16; m += 16) {
197
+ // load 16 uint8 values
198
+ __m128i mm1[N];
199
+ mm1[0] = _mm_loadu_si128((const __m128i_u*)(code0 + m));
200
+ mm1[1] = _mm_loadu_si128((const __m128i_u*)(code1 + m));
201
+ mm1[2] = _mm_loadu_si128((const __m128i_u*)(code2 + m));
202
+ mm1[3] = _mm_loadu_si128((const __m128i_u*)(code3 + m));
203
+
204
+ // process first 8 codes
205
+ for (intptr_t j = 0; j < N; j++) {
206
+ const __m512i idx1 = _mm512_cvtepu8_epi32(mm1[j]);
207
+
208
+ // add offsets
209
+ const __m512i indices_to_read_from =
210
+ _mm512_add_epi32(idx1, offsets_0);
211
+
212
+ // gather 16 values, similar to 16 operations of tab[idx]
213
+ __m512 collected = _mm512_i32gather_ps(
214
+ indices_to_read_from, tab, sizeof(float));
215
+
216
+ // collect partial sums
217
+ partialSums[j] = _mm512_add_ps(partialSums[j], collected);
218
+ }
219
+ tab += ksub * 16;
220
+ }
221
+
222
+ // horizontal sum for partialSum
223
+ result0 += _mm512_reduce_add_ps(partialSums[0]);
224
+ result1 += _mm512_reduce_add_ps(partialSums[1]);
225
+ result2 += _mm512_reduce_add_ps(partialSums[2]);
226
+ result3 += _mm512_reduce_add_ps(partialSums[3]);
227
+ }
228
+
229
+ //
230
+ if (m < M) {
231
+ // process leftovers
232
+ PQDecoder8 decoder0(code0 + m, nbits);
233
+ PQDecoder8 decoder1(code1 + m, nbits);
234
+ PQDecoder8 decoder2(code2 + m, nbits);
235
+ PQDecoder8 decoder3(code3 + m, nbits);
236
+ for (; m < M; m++) {
237
+ result0 += tab[decoder0.decode()];
238
+ result1 += tab[decoder1.decode()];
239
+ result2 += tab[decoder2.decode()];
240
+ result3 += tab[decoder3.decode()];
241
+ tab += ksub;
242
+ }
243
+ }
244
+ }
245
+
246
+ } // namespace faiss
247
+
248
+ #endif
@@ -7,27 +7,31 @@
7
7
 
8
8
  #pragma once
9
9
 
10
- #include <faiss/impl/ProductQuantizer.h>
10
+ #include <cstddef>
11
+ #include <cstdint>
11
12
 
12
13
  namespace faiss {
13
14
 
14
15
  /// Returns the distance to a single code.
15
16
  template <typename PQDecoderT>
16
17
  inline float distance_single_code_generic(
17
- // the product quantizer
18
- const ProductQuantizer& pq,
18
+ // number of subquantizers
19
+ const size_t M,
20
+ // number of bits per quantization index
21
+ const size_t nbits,
19
22
  // precomputed distances, layout (M, ksub)
20
23
  const float* sim_table,
21
24
  // the code
22
25
  const uint8_t* code) {
23
- PQDecoderT decoder(code, pq.nbits);
26
+ PQDecoderT decoder(code, nbits);
27
+ const size_t ksub = 1 << nbits;
24
28
 
25
29
  const float* tab = sim_table;
26
30
  float result = 0;
27
31
 
28
- for (size_t m = 0; m < pq.M; m++) {
32
+ for (size_t m = 0; m < M; m++) {
29
33
  result += tab[decoder.decode()];
30
- tab += pq.ksub;
34
+ tab += ksub;
31
35
  }
32
36
 
33
37
  return result;
@@ -37,8 +41,10 @@ inline float distance_single_code_generic(
37
41
  /// General-purpose version.
38
42
  template <typename PQDecoderT>
39
43
  inline void distance_four_codes_generic(
40
- // the product quantizer
41
- const ProductQuantizer& pq,
44
+ // number of subquantizers
45
+ const size_t M,
46
+ // number of bits per quantization index
47
+ const size_t nbits,
42
48
  // precomputed distances, layout (M, ksub)
43
49
  const float* sim_table,
44
50
  // codes
@@ -51,10 +57,11 @@ inline void distance_four_codes_generic(
51
57
  float& result1,
52
58
  float& result2,
53
59
  float& result3) {
54
- PQDecoderT decoder0(code0, pq.nbits);
55
- PQDecoderT decoder1(code1, pq.nbits);
56
- PQDecoderT decoder2(code2, pq.nbits);
57
- PQDecoderT decoder3(code3, pq.nbits);
60
+ PQDecoderT decoder0(code0, nbits);
61
+ PQDecoderT decoder1(code1, nbits);
62
+ PQDecoderT decoder2(code2, nbits);
63
+ PQDecoderT decoder3(code3, nbits);
64
+ const size_t ksub = 1 << nbits;
58
65
 
59
66
  const float* tab = sim_table;
60
67
  result0 = 0;
@@ -62,12 +69,12 @@ inline void distance_four_codes_generic(
62
69
  result2 = 0;
63
70
  result3 = 0;
64
71
 
65
- for (size_t m = 0; m < pq.M; m++) {
72
+ for (size_t m = 0; m < M; m++) {
66
73
  result0 += tab[decoder0.decode()];
67
74
  result1 += tab[decoder1.decode()];
68
75
  result2 += tab[decoder2.decode()];
69
76
  result3 += tab[decoder3.decode()];
70
- tab += pq.ksub;
77
+ tab += ksub;
71
78
  }
72
79
  }
73
80
 
@@ -32,19 +32,23 @@ namespace faiss {
32
32
 
33
33
  template <typename PQDecoderT>
34
34
  inline float distance_single_code(
35
- // the product quantizer
36
- const ProductQuantizer& pq,
35
+ // number of subquantizers
36
+ const size_t M,
37
+ // number of bits per quantization index
38
+ const size_t nbits,
37
39
  // precomputed distances, layout (M, ksub)
38
40
  const float* sim_table,
39
41
  // the code
40
42
  const uint8_t* code) {
41
- return distance_single_code_avx2<PQDecoderT>(pq, sim_table, code);
43
+ return distance_single_code_avx2<PQDecoderT>(M, nbits, sim_table, code);
42
44
  }
43
45
 
44
46
  template <typename PQDecoderT>
45
47
  inline void distance_four_codes(
46
- // the product quantizer
47
- const ProductQuantizer& pq,
48
+ // number of subquantizers
49
+ const size_t M,
50
+ // number of bits per quantization index
51
+ const size_t nbits,
48
52
  // precomputed distances, layout (M, ksub)
49
53
  const float* sim_table,
50
54
  // codes
@@ -58,7 +62,8 @@ inline void distance_four_codes(
58
62
  float& result2,
59
63
  float& result3) {
60
64
  distance_four_codes_avx2<PQDecoderT>(
61
- pq,
65
+ M,
66
+ nbits,
62
67
  sim_table,
63
68
  code0,
64
69
  code1,
@@ -80,19 +85,23 @@ namespace faiss {
80
85
 
81
86
  template <typename PQDecoderT>
82
87
  inline float distance_single_code(
83
- // the product quantizer
84
- const ProductQuantizer& pq,
88
+ // number of subquantizers
89
+ const size_t M,
90
+ // number of bits per quantization index
91
+ const size_t nbits,
85
92
  // precomputed distances, layout (M, ksub)
86
93
  const float* sim_table,
87
94
  // the code
88
95
  const uint8_t* code) {
89
- return distance_single_code_generic<PQDecoderT>(pq, sim_table, code);
96
+ return distance_single_code_generic<PQDecoderT>(M, nbits, sim_table, code);
90
97
  }
91
98
 
92
99
  template <typename PQDecoderT>
93
100
  inline void distance_four_codes(
94
- // the product quantizer
95
- const ProductQuantizer& pq,
101
+ // number of subquantizers
102
+ const size_t M,
103
+ // number of bits per quantization index
104
+ const size_t nbits,
96
105
  // precomputed distances, layout (M, ksub)
97
106
  const float* sim_table,
98
107
  // codes
@@ -106,7 +115,8 @@ inline void distance_four_codes(
106
115
  float& result2,
107
116
  float& result3) {
108
117
  distance_four_codes_generic<PQDecoderT>(
109
- pq,
118
+ M,
119
+ nbits,
110
120
  sim_table,
111
121
  code0,
112
122
  code1,