faiss 0.6.4 → 0.6.5

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 (228) 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/vendor/faiss/faiss/AutoTune.cpp +175 -0
  6. data/vendor/faiss/faiss/Clustering.cpp +150 -60
  7. data/vendor/faiss/faiss/Clustering.h +29 -0
  8. data/vendor/faiss/faiss/IVFlib.cpp +99 -0
  9. data/vendor/faiss/faiss/IVFlib.h +15 -0
  10. data/vendor/faiss/faiss/Index.cpp +44 -0
  11. data/vendor/faiss/faiss/Index.h +19 -14
  12. data/vendor/faiss/faiss/IndexBinary.cpp +8 -0
  13. data/vendor/faiss/faiss/IndexBinary.h +8 -0
  14. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +82 -4
  15. data/vendor/faiss/faiss/IndexBinaryHNSW.h +19 -0
  16. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +34 -0
  17. data/vendor/faiss/faiss/IndexFastScan.cpp +33 -17
  18. data/vendor/faiss/faiss/IndexFastScan.h +6 -3
  19. data/vendor/faiss/faiss/IndexFlat.cpp +56 -0
  20. data/vendor/faiss/faiss/IndexFlat.h +31 -0
  21. data/vendor/faiss/faiss/IndexFlatCodes.cpp +6 -1
  22. data/vendor/faiss/faiss/IndexHNSW.cpp +456 -10
  23. data/vendor/faiss/faiss/IndexHNSW.h +38 -0
  24. data/vendor/faiss/faiss/IndexIDMap.cpp +32 -0
  25. data/vendor/faiss/faiss/IndexIDMap.h +7 -0
  26. data/vendor/faiss/faiss/IndexIVF.cpp +281 -31
  27. data/vendor/faiss/faiss/IndexIVF.h +53 -1
  28. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +46 -14
  29. data/vendor/faiss/faiss/IndexIVFFastScan.h +4 -2
  30. data/vendor/faiss/faiss/IndexIVFFlat.cpp +33 -0
  31. data/vendor/faiss/faiss/IndexIVFFlat.h +16 -0
  32. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1 -0
  33. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +3 -20
  34. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +50 -14
  35. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -2
  36. data/vendor/faiss/faiss/IndexIVFSQFastScan.cpp +855 -0
  37. data/vendor/faiss/faiss/IndexIVFSQFastScan.h +145 -0
  38. data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -3
  39. data/vendor/faiss/faiss/IndexPiPNN.cpp +201 -0
  40. data/vendor/faiss/faiss/IndexPiPNN.h +83 -0
  41. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +6 -3
  42. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +10 -4
  43. data/vendor/faiss/faiss/IndexReplicas.cpp +20 -0
  44. data/vendor/faiss/faiss/IndexReplicas.h +9 -0
  45. data/vendor/faiss/faiss/IndexSQFastScan.cpp +648 -0
  46. data/vendor/faiss/faiss/IndexSQFastScan.h +129 -0
  47. data/vendor/faiss/faiss/IndexShards.cpp +10 -0
  48. data/vendor/faiss/faiss/IndexShards.h +5 -0
  49. data/vendor/faiss/faiss/SuperKMeans.cpp +57 -15
  50. data/vendor/faiss/faiss/SuperKMeans.h +9 -4
  51. data/vendor/faiss/faiss/VectorTransform.cpp +3 -2
  52. data/vendor/faiss/faiss/clone_index.cpp +24 -0
  53. data/vendor/faiss/faiss/gpu/Dataset.h +112 -0
  54. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +16 -13
  55. data/vendor/faiss/faiss/gpu/GpuCloner.h +4 -0
  56. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -0
  57. data/vendor/faiss/faiss/gpu/GpuIndex.h +4 -13
  58. data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +26 -13
  59. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +45 -22
  60. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -0
  61. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
  62. data/vendor/faiss/faiss/gpu/test/TestGpuDatasetHeader.cpp +18 -0
  63. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +215 -0
  64. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +98 -0
  65. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +11 -0
  66. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -1
  67. data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +11 -0
  68. data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +92 -0
  69. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +4 -0
  70. data/vendor/faiss/faiss/gpu_metal/MetalIndexBinaryFlat.h +69 -0
  71. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +38 -0
  72. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +106 -0
  73. data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +10 -0
  74. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +2 -0
  75. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +1 -6
  76. data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +134 -45
  77. data/vendor/faiss/faiss/impl/ClusteringHelpers.h +36 -0
  78. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +286 -136
  79. data/vendor/faiss/faiss/impl/DistanceComputer.cpp +63 -0
  80. data/vendor/faiss/faiss/impl/DistanceComputer.h +3 -29
  81. data/vendor/faiss/faiss/impl/HNSW.cpp +46 -10
  82. data/vendor/faiss/faiss/impl/HNSW.h +72 -0
  83. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +6 -19
  84. data/vendor/faiss/faiss/impl/NNDescent.cpp +2 -1
  85. data/vendor/faiss/faiss/impl/NSG.cpp +3 -2
  86. data/vendor/faiss/faiss/impl/Panorama.h +3 -2
  87. data/vendor/faiss/faiss/impl/PiPNN.cpp +822 -0
  88. data/vendor/faiss/faiss/impl/PiPNN.h +122 -0
  89. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +54 -11
  90. data/vendor/faiss/faiss/impl/RaBitQUtils.h +1 -1
  91. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +81 -57
  92. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +15 -0
  93. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -0
  94. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -6
  95. data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +0 -4
  96. data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +0 -4
  97. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +5 -2
  98. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +0 -4
  99. data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +0 -4
  100. data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +0 -4
  101. data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +0 -4
  102. data/vendor/faiss/faiss/impl/expanded_scanners.h +88 -0
  103. data/vendor/faiss/faiss/impl/fast_scan/FastScanDistancePostProcessing.h +4 -0
  104. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +61 -64
  105. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +13 -14
  106. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +17 -129
  107. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +25 -19
  108. data/vendor/faiss/faiss/impl/fast_scan/fast_scan.cpp +5 -0
  109. data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +0 -4
  110. data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +0 -4
  111. data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +0 -88
  112. data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +0 -4
  113. data/vendor/faiss/faiss/impl/fast_scan/kernels_neon.h +155 -0
  114. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +22 -1
  115. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd512.h +3 -2
  116. data/vendor/faiss/faiss/impl/fast_scan/simd_result_handlers.h +41 -23
  117. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +0 -4
  118. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +0 -4
  119. data/vendor/faiss/faiss/impl/index_read.cpp +172 -0
  120. data/vendor/faiss/faiss/impl/index_write.cpp +95 -0
  121. data/vendor/faiss/faiss/impl/pipnn/HashPrune.cpp +159 -0
  122. data/vendor/faiss/faiss/impl/pipnn/HashPrune.h +69 -0
  123. data/vendor/faiss/faiss/impl/pipnn/Partition.cpp +587 -0
  124. data/vendor/faiss/faiss/impl/pipnn/Partition.h +93 -0
  125. data/vendor/faiss/faiss/impl/pipnn/kernels.cpp +326 -0
  126. data/vendor/faiss/faiss/impl/pipnn/kernels.h +92 -0
  127. data/vendor/faiss/faiss/impl/platform_macros.h +45 -0
  128. data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +0 -4
  129. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +79 -4
  130. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +6 -0
  131. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +0 -4
  132. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +0 -4
  133. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +0 -4
  134. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx2.h +4 -0
  135. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx512.h +4 -1
  136. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +19 -0
  137. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +6 -6
  138. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +131 -6
  139. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +0 -4
  140. data/vendor/faiss/faiss/impl/pq_code_distance/pq_rvv_kernel.h +89 -0
  141. data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +21 -10
  142. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +45 -18
  143. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +2 -1
  144. data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +0 -4
  145. data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +0 -4
  146. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +0 -4
  147. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +0 -4
  148. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +5 -1
  149. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +28 -52
  150. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +59 -11
  151. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +226 -77
  152. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +482 -103
  153. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +2 -149
  154. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +3 -698
  155. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +66 -57
  156. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +101 -96
  157. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +3185 -144
  158. data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_coefficients.h +48 -0
  159. data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_rvv_kernel.h +546 -0
  160. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +2 -2
  161. data/vendor/faiss/faiss/impl/simd_dispatch.h +7 -0
  162. data/vendor/faiss/faiss/impl/simdlib/simdlib_avx2.h +14 -0
  163. data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +7 -8
  164. data/vendor/faiss/faiss/impl/sq_fastscan_utils.h +232 -0
  165. data/vendor/faiss/faiss/index_factory.cpp +76 -0
  166. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +3 -1
  167. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +3 -2
  168. data/vendor/faiss/faiss/utils/AlignedTable.h +6 -1
  169. data/vendor/faiss/faiss/utils/Heap.cpp +4 -3
  170. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +16 -5
  171. data/vendor/faiss/faiss/utils/bf16.h +36 -0
  172. data/vendor/faiss/faiss/utils/distances.cpp +226 -15
  173. data/vendor/faiss/faiss/utils/distances.h +34 -0
  174. data/vendor/faiss/faiss/utils/distances_dispatch.h +6 -4
  175. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +2 -5
  176. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +0 -14
  177. data/vendor/faiss/faiss/utils/distances_fused/rvv.cpp +25 -0
  178. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +0 -4
  179. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +0 -4
  180. data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +2 -1
  181. data/vendor/faiss/faiss/utils/distances_simd.cpp +9 -0
  182. data/vendor/faiss/faiss/utils/fp16-fp16c.h +4 -0
  183. data/vendor/faiss/faiss/utils/fp16-inl.h +26 -52
  184. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +0 -4
  185. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +0 -4
  186. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +0 -4
  187. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +33 -5
  188. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_vpopcnt.h +15 -30
  189. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +0 -4
  190. data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +2 -1
  191. data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +0 -4
  192. data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +0 -4
  193. data/vendor/faiss/faiss/utils/pq_code_distance.h +8 -4
  194. data/vendor/faiss/faiss/utils/prefetch.h +1 -26
  195. data/vendor/faiss/faiss/utils/quantize_lut.cpp +26 -27
  196. data/vendor/faiss/faiss/utils/quantize_lut.h +11 -0
  197. data/vendor/faiss/faiss/utils/rabitq_simd.h +51 -16
  198. data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +9 -4
  199. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +37 -5
  200. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +64 -5
  201. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +64 -5
  202. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +353 -71
  203. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv_kernel.h +68 -0
  204. data/vendor/faiss/faiss/utils/simd_impl/exhaustive_L2sqr_blas_cmax.h +93 -0
  205. data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels.h +76 -0
  206. data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx2.cpp +52 -0
  207. data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx512.cpp +52 -0
  208. data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_neon.cpp +48 -0
  209. data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx2.h +44 -0
  210. data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx512.h +43 -0
  211. data/vendor/faiss/faiss/utils/simd_impl/masked_sum.h +38 -0
  212. data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +0 -4
  213. data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +0 -4
  214. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +54 -15
  215. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +38 -21
  216. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_vpopcnt.cpp +51 -14
  217. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +297 -10
  218. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +0 -4
  219. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +0 -4
  220. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +0 -4
  221. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +0 -4
  222. data/vendor/faiss/faiss/utils/simd_levels.cpp +19 -3
  223. data/vendor/faiss/faiss/utils/simd_levels.h +74 -1
  224. data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +0 -4
  225. data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +0 -4
  226. data/vendor/faiss/faiss/utils/utils.cpp +80 -0
  227. data/vendor/faiss/faiss/utils/utils.h +24 -0
  228. metadata +33 -1
@@ -0,0 +1,326 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and 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/pipnn/kernels.h>
9
+
10
+ #include <algorithm>
11
+ #include <cmath>
12
+ #include <limits>
13
+ #include <memory>
14
+ #include <typeinfo>
15
+ #include <vector>
16
+
17
+ #include <faiss/IndexScalarQuantizer.h>
18
+ #include <faiss/impl/FaissAssert.h>
19
+ #include <faiss/utils/Heap.h>
20
+
21
+ extern "C" {
22
+
23
+ // this is to keep the clang syntax checker happy
24
+ #ifndef FINTEGER
25
+ #define FINTEGER int
26
+ #endif
27
+
28
+ /* declare BLAS functions, see http://www.netlib.org/clapack/cblas/ */
29
+
30
+ int sgemm_(
31
+ const char* transa,
32
+ const char* transb,
33
+ FINTEGER* m,
34
+ FINTEGER* n,
35
+ FINTEGER* k,
36
+ const float* alpha,
37
+ const float* a,
38
+ FINTEGER* lda,
39
+ const float* b,
40
+ FINTEGER* ldb,
41
+ float* beta,
42
+ float* c,
43
+ FINTEGER* ldc);
44
+
45
+ int ssyrk_(
46
+ const char* uplo,
47
+ const char* trans,
48
+ FINTEGER* n,
49
+ FINTEGER* k,
50
+ float* alpha,
51
+ float* a,
52
+ FINTEGER* lda,
53
+ float* beta,
54
+ float* c,
55
+ FINTEGER* ldc);
56
+ }
57
+
58
+ namespace faiss {
59
+ namespace pipnn {
60
+
61
+ namespace {
62
+
63
+ FINTEGER to_finteger(size_t v, const char* what) {
64
+ FAISS_THROW_IF_NOT_FMT(
65
+ v <= size_t(std::numeric_limits<FINTEGER>::max()),
66
+ "PiPNN kernel: %s=%zu exceeds the BLAS integer range",
67
+ what,
68
+ v);
69
+ return static_cast<FINTEGER>(v);
70
+ }
71
+
72
+ float nan_to_inf(float v) {
73
+ return std::isnan(v) ? std::numeric_limits<float>::infinity() : v;
74
+ }
75
+
76
+ /// Top-k in (dist, index) order on a Faiss max-heap. Empty slots are
77
+ /// (+inf, INT32_MAX), so +inf offers still fill them, in index order.
78
+ using TopK = CMax<float, int32_t>;
79
+ constexpr int32_t kEmpty = std::numeric_limits<int32_t>::max();
80
+
81
+ void topk_init(float* D, int32_t* I, size_t k) {
82
+ std::fill(D, D + k, std::numeric_limits<float>::infinity());
83
+ std::fill(I, I + k, kEmpty);
84
+ }
85
+
86
+ void topk_offer(float* D, int32_t* I, size_t k, float v, int32_t id) {
87
+ if (TopK::cmp2(D[0], v, I[0], id)) {
88
+ heap_replace_top<TopK>(k, D, I, v, id);
89
+ }
90
+ }
91
+
92
+ /// Sorts the slots by (dist, index); slots never filled become (+inf, -1).
93
+ void topk_finish(float* D, int32_t* I, size_t k) {
94
+ heap_reorder<TopK>(k, D, I);
95
+ std::replace(I, I + k, kEmpty, int32_t(-1));
96
+ }
97
+
98
+ } // namespace
99
+
100
+ void stripe_assign(
101
+ const float* points,
102
+ size_t S,
103
+ const float* leaders,
104
+ const float* leader_norms,
105
+ size_t L,
106
+ size_t d,
107
+ Ranking ranking,
108
+ int fanout,
109
+ float* scratch,
110
+ uint16_t* out) {
111
+ FAISS_THROW_IF_NOT_FMT(
112
+ L >= 1 && L <= 65535,
113
+ "stripe_assign: L=%zu must be in [1, 65535]",
114
+ L);
115
+ FAISS_THROW_IF_NOT_FMT(
116
+ fanout >= 1 && size_t(fanout) <= L,
117
+ "stripe_assign: fanout=%d must be in [1, L=%zu]",
118
+ fanout,
119
+ L);
120
+ FAISS_THROW_IF_NOT_MSG(d >= 1, "stripe_assign: d must be >= 1");
121
+ FAISS_THROW_IF_NOT_MSG(
122
+ ranking == Ranking::IP || leader_norms,
123
+ "stripe_assign: leader_norms is required for the L2 and Angle rankings");
124
+ if (S == 0) {
125
+ return;
126
+ }
127
+ FINTEGER li = to_finteger(L, "L");
128
+ FINTEGER si = to_finteger(S, "S");
129
+ FINTEGER di = to_finteger(d, "d");
130
+
131
+ // Column-major BLAS sees row-major scratch (S x L) as L x S, so "T", "N"
132
+ // gives scratch[i * L + j] = alpha * p_i.l_j + beta * scratch[i * L + j].
133
+ float alpha = -1;
134
+ float beta = 0; // BLAS does not read C when beta == 0
135
+ if (ranking == Ranking::L2) {
136
+ for (size_t i = 0; i < S; i++) {
137
+ std::copy(leader_norms, leader_norms + L, scratch + i * L);
138
+ }
139
+ alpha = -2;
140
+ beta = 1;
141
+ }
142
+ sgemm_("T",
143
+ "N",
144
+ &li,
145
+ &si,
146
+ &di,
147
+ &alpha,
148
+ leaders,
149
+ &di,
150
+ points,
151
+ &di,
152
+ &beta,
153
+ scratch,
154
+ &li);
155
+
156
+ if (ranking == Ranking::Angle) {
157
+ // A zero-norm leader has no direction: rank it +inf, not the -inf of
158
+ // a positive dot product divided by 0.
159
+ for (size_t i = 0; i < S; i++) {
160
+ float* row = scratch + i * L;
161
+ for (size_t j = 0; j < L; j++) {
162
+ const float len = std::sqrt(leader_norms[j]);
163
+ row[j] = len > 0 ? row[j] / len
164
+ : std::numeric_limits<float>::infinity();
165
+ }
166
+ }
167
+ }
168
+
169
+ const size_t f = size_t(fanout);
170
+ std::vector<float> D(f);
171
+ std::vector<int32_t> I(f);
172
+ for (size_t i = 0; i < S; i++) {
173
+ topk_init(D.data(), I.data(), f);
174
+ const float* row = scratch + i * L;
175
+ for (size_t j = 0; j < L; j++) {
176
+ topk_offer(D.data(), I.data(), f, nan_to_inf(row[j]), int32_t(j));
177
+ }
178
+ topk_finish(D.data(), I.data(), f);
179
+ // L >= fanout and every offer precedes an empty slot, so all fanout
180
+ // slots are filled, even when the whole row is +inf.
181
+ for (size_t r = 0; r < f; r++) {
182
+ out[i * f + r] = uint16_t(I[r]);
183
+ }
184
+ }
185
+ }
186
+
187
+ namespace {
188
+
189
+ /// Distance from a Gram entry: L2 max(0, ni + nj - 2g), IP -g. NaN is mapped
190
+ /// to +inf before the L2 clamp, which would otherwise turn it into 0.
191
+ float gram_to_distance(bool is_l2, float ni, float nj, float g) {
192
+ if (is_l2) {
193
+ const float v = ni + nj - 2 * g;
194
+ if (std::isnan(v)) {
195
+ return std::numeric_limits<float>::infinity();
196
+ }
197
+ return v < 0 ? 0 : v;
198
+ }
199
+ return nan_to_inf(-g);
200
+ }
201
+
202
+ /// Lower triangle of X X^T, diagonal included, into row-major gram (s x s);
203
+ /// the strict upper triangle is not written.
204
+ void gram_lower(const float* X, size_t s, size_t d, float* gram) {
205
+ // Column-major BLAS reads X as A = X^T (d x s); the upper triangle of
206
+ // C = A^T A ("U", "T") is the row-major lower triangle of gram.
207
+ FINTEGER si = to_finteger(s, "s");
208
+ FINTEGER di = to_finteger(d, "d");
209
+ float one = 1;
210
+ float zero = 0; // BLAS does not read C when beta == 0
211
+ ssyrk_("U",
212
+ "T",
213
+ &si,
214
+ &di,
215
+ &one,
216
+ const_cast<float*>(X),
217
+ &di,
218
+ &zero,
219
+ gram,
220
+ &si);
221
+ }
222
+
223
+ } // namespace
224
+
225
+ void leaf_knn(
226
+ const float* X,
227
+ const float* norms,
228
+ size_t s,
229
+ size_t d,
230
+ MetricType metric,
231
+ int k,
232
+ float* gram,
233
+ int32_t* nn_idx,
234
+ float* nn_dist) {
235
+ FAISS_THROW_IF_NOT_MSG(
236
+ metric == METRIC_L2 || metric == METRIC_INNER_PRODUCT,
237
+ "leaf_knn: metric must be METRIC_L2 or METRIC_INNER_PRODUCT");
238
+ FAISS_THROW_IF_NOT_MSG(k >= 1, "leaf_knn: k must be >= 1");
239
+ FAISS_THROW_IF_NOT_MSG(d >= 1, "leaf_knn: d must be >= 1");
240
+ FAISS_THROW_IF_NOT_MSG(
241
+ metric == METRIC_INNER_PRODUCT || norms,
242
+ "leaf_knn: norms is required for METRIC_L2");
243
+ const size_t kk = size_t(k);
244
+ for (size_t i = 0; i < s; i++) {
245
+ topk_init(nn_dist + i * kk, nn_idx + i * kk, kk);
246
+ }
247
+ if (s >= 2) {
248
+ gram_lower(X, s, d, gram);
249
+ }
250
+ const bool is_l2 = metric == METRIC_L2;
251
+ for (size_t i = 1; i < s; i++) {
252
+ const float* gi = gram + i * s;
253
+ const float ni = is_l2 ? norms[i] : 0;
254
+ for (size_t j = 0; j < i; j++) {
255
+ const float nj = is_l2 ? norms[j] : 0;
256
+ const float v = gram_to_distance(is_l2, ni, nj, gi[j]);
257
+ topk_offer(nn_dist + i * kk, nn_idx + i * kk, kk, v, int32_t(j));
258
+ topk_offer(nn_dist + j * kk, nn_idx + j * kk, kk, v, int32_t(i));
259
+ }
260
+ }
261
+ for (size_t i = 0; i < s; i++) {
262
+ topk_finish(nn_dist + i * kk, nn_idx + i * kk, kk);
263
+ }
264
+ }
265
+
266
+ void pairwise_distances(
267
+ const float* X,
268
+ const float* norms,
269
+ size_t n,
270
+ size_t d,
271
+ MetricType metric,
272
+ float* out) {
273
+ FAISS_THROW_IF_NOT_MSG(
274
+ metric == METRIC_L2 || metric == METRIC_INNER_PRODUCT,
275
+ "pairwise_distances: metric must be METRIC_L2 or METRIC_INNER_PRODUCT");
276
+ FAISS_THROW_IF_NOT_MSG(d >= 1, "pairwise_distances: d must be >= 1");
277
+ FAISS_THROW_IF_NOT_MSG(
278
+ metric == METRIC_INNER_PRODUCT || norms,
279
+ "pairwise_distances: norms is required for METRIC_L2");
280
+ if (n == 0) {
281
+ return;
282
+ }
283
+ // Row i reads only its lower part of the Gram scratch; mirrored writes of
284
+ // earlier rows go to their strict upper triangle.
285
+ gram_lower(X, n, d, out);
286
+ const bool is_l2 = metric == METRIC_L2;
287
+ for (size_t i = 0; i < n; i++) {
288
+ float* oi = out + i * n;
289
+ const float ni = is_l2 ? norms[i] : 0;
290
+ for (size_t j = 0; j < i; j++) {
291
+ const float nj = is_l2 ? norms[j] : 0;
292
+ const float v = gram_to_distance(is_l2, ni, nj, oi[j]);
293
+ oi[j] = v;
294
+ out[j * n + i] = v;
295
+ }
296
+ oi[i] = gram_to_distance(is_l2, ni, ni, oi[i]);
297
+ }
298
+ }
299
+
300
+ void gather_rows(
301
+ const Index& storage,
302
+ const int32_t* ids,
303
+ size_t k,
304
+ float* out) {
305
+ const size_t d = static_cast<size_t>(storage.d);
306
+ if (typeid(storage) == typeid(IndexScalarQuantizer)) {
307
+ // Not reconstruct: ScalarQuantizer::decode opens an OpenMP region, and
308
+ // a nested region inside the build's dynamic loops crashes libomp.
309
+ const auto& sq = static_cast<const IndexScalarQuantizer&>(storage);
310
+ std::unique_ptr<ScalarQuantizer::SQuantizer> quant(
311
+ sq.sq.select_quantizer());
312
+ for (size_t i = 0; i < k; i++) {
313
+ quant->decode_vector(
314
+ sq.codes.data() +
315
+ static_cast<size_t>(ids[i]) * sq.code_size,
316
+ out + i * d);
317
+ }
318
+ return;
319
+ }
320
+ for (size_t i = 0; i < k; i++) {
321
+ storage.reconstruct(ids[i], out + i * d);
322
+ }
323
+ }
324
+
325
+ } // namespace pipnn
326
+ } // namespace faiss
@@ -0,0 +1,92 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and 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
+ #include <faiss/MetricType.h>
11
+ #include <faiss/utils/AlignedTable.h>
12
+ #include <cstddef>
13
+ #include <cstdint>
14
+
15
+ /*
16
+ * Each kernel makes one BLAS call (sgemm_ or ssyrk_), and results are bitwise
17
+ * reproducible across thread counts only if that call runs single-threaded.
18
+ * So call the kernels inside an OpenMP parallel region, or from serial code
19
+ * only when omp_get_max_threads() == 1, and keep BLAS from threading on its
20
+ * own: MKL_NUM_THREADS unset or 1, OPENBLAS_NUM_THREADS=1 for pthreads
21
+ * OpenBLAS, VECLIB_MAXIMUM_THREADS=1 on macOS, OMP_NUM_THREADS=1 for an
22
+ * OpenMP BLAS in a Faiss build without OpenMP. Inputs should be 64-byte
23
+ * aligned: some BLAS round differently on differently aligned buffers.
24
+ */
25
+
26
+ namespace faiss {
27
+
28
+ struct Index;
29
+
30
+ namespace pipnn {
31
+
32
+ /// Points per stripe item of the partition kernel. Changing it changes graphs.
33
+ constexpr size_t kStripe = 1024;
34
+
35
+ enum class Ranking : uint8_t { L2 = 0, IP = 1, Angle = 2 };
36
+
37
+ /// out (S x fanout): each point's nearest leaders in (rank, index) order, with
38
+ /// rank L2 ||l||^2 - 2 p.l, IP -p.l, Angle -p.l / ||l|| (+inf if ||l|| = 0).
39
+ /// NaN ranks +inf. scratch: S * L floats; leader_norms may be null for IP.
40
+ void stripe_assign(
41
+ const float* points,
42
+ size_t S,
43
+ const float* leaders,
44
+ const float* leader_norms,
45
+ size_t L,
46
+ size_t d,
47
+ Ranking ranking,
48
+ int fanout,
49
+ float* scratch,
50
+ uint16_t* out);
51
+
52
+ /// k nearest neighbours (s x k) of each leaf point in (dist, index) order;
53
+ /// unfilled slots are -1 / +inf. gram: s * s floats; norms null for IP only.
54
+ void leaf_knn(
55
+ const float* X,
56
+ const float* norms,
57
+ size_t s,
58
+ size_t d,
59
+ MetricType metric,
60
+ int k,
61
+ float* gram,
62
+ int32_t* nn_idx,
63
+ float* nn_dist);
64
+
65
+ /// n x n distances (L2 clamped at 0, IP -dot); out is also the Gram scratch.
66
+ /// The L2 diagonal is small and non-negative, but not necessarily 0.
67
+ void pairwise_distances(
68
+ const float* X,
69
+ const float* norms,
70
+ size_t n,
71
+ size_t d,
72
+ MetricType metric,
73
+ float* out);
74
+
75
+ /// Rows ids[0..k) of `storage` as floats into out (k x d). SQ rows are decoded
76
+ /// directly; other types use reconstruct(), which must not open OpenMP regions.
77
+ void gather_rows(
78
+ const Index& storage,
79
+ const int32_t* ids,
80
+ size_t k,
81
+ float* out);
82
+
83
+ /// Grows a per-thread scratch table and never shrinks it: AlignedTable::resize
84
+ /// reallocates whenever the rounded capacity changes, shrinking included.
85
+ inline void ensure_size(AlignedTable<float, 64>& table, size_t n) {
86
+ if (table.size() < n) {
87
+ table.resize(n);
88
+ }
89
+ }
90
+
91
+ } // namespace pipnn
92
+ } // namespace faiss
@@ -8,6 +8,7 @@
8
8
  #pragma once
9
9
 
10
10
  // basic int types and size_t
11
+ #include <atomic>
11
12
  #include <cstdint>
12
13
  #include <cstdio>
13
14
 
@@ -146,6 +147,33 @@ inline int __builtin_clzll(uint64_t x) {
146
147
  #define FAISS_DEPRECATED(msg)
147
148
  #endif // GCC or Clang
148
149
 
150
+ // Never inlined, so floating-point results do not depend on the compile
151
+ // flags of the call site (e.g. under LTO).
152
+ #if defined(_MSC_VER)
153
+ #define FAISS_NOINLINE __declspec(noinline)
154
+ #elif defined(__clang__)
155
+ #define FAISS_NOINLINE __attribute__((noinline))
156
+ #elif defined(__GNUC__)
157
+ #define FAISS_NOINLINE __attribute__((noinline, noclone))
158
+ #else
159
+ #define FAISS_NOINLINE
160
+ #endif
161
+
162
+ namespace faiss {
163
+ namespace detail {
164
+
165
+ template <typename T>
166
+ inline void atomic_fetch_add_relaxed(T& target, T value) {
167
+ #if defined(__cpp_lib_atomic_ref) && __cpp_lib_atomic_ref >= 201806L
168
+ std::atomic_ref<T>(target).fetch_add(value, std::memory_order_relaxed);
169
+ #else
170
+ __atomic_fetch_add(&target, value, __ATOMIC_RELAXED);
171
+ #endif
172
+ }
173
+
174
+ } // namespace detail
175
+ } // namespace faiss
176
+
149
177
  // Localized enablement of imprecise floating point operations
150
178
  // You need to use all 3 macros to cover all compilers.
151
179
  #if defined(_MSC_VER)
@@ -226,3 +254,20 @@ inline int __builtin_clzll(uint64_t x) {
226
254
  #define FAISS_MAYBE_UNUSED [[maybe_unused]]
227
255
  #define FAISS_FINAL final
228
256
  #endif
257
+
258
+ /*******************************************************
259
+ * OpenMP dynamic scheduling
260
+ *******************************************************/
261
+
262
+ // Use as schedule(FAISS_OMP_DYNAMIC) or schedule(FAISS_OMP_DYNAMIC, chunk).
263
+ // OpenMP 5.0 makes schedule(dynamic) nonmonotonic, and libomp 12 runs
264
+ // nonmonotonic dynamic loops with its static-steal scheduler, which crashes
265
+ // intermittently under load (libomp itself keeps it off by default). MSVC's
266
+ // OpenMP 2.0 has no schedule modifiers.
267
+ // clang-format off
268
+ #ifdef _MSC_VER
269
+ #define FAISS_OMP_DYNAMIC dynamic
270
+ #else
271
+ #define FAISS_OMP_DYNAMIC monotonic : dynamic
272
+ #endif
273
+ // clang-format on
@@ -7,8 +7,6 @@
7
7
 
8
8
  // -*- c++ -*-
9
9
 
10
- #ifdef COMPILE_SIMD_AVX512
11
-
12
10
  #include <faiss/impl/PolysemousTraining.h>
13
11
  #include <faiss/impl/polysemous_training/dispatch.h>
14
12
  #include <faiss/utils/popcount.h>
@@ -280,5 +278,3 @@ double distances_cost_update<SIMDLevel::AVX512>(
280
278
 
281
279
  } // namespace polysemous_training
282
280
  } // namespace faiss
283
-
284
- #endif // COMPILE_SIMD_AVX512
@@ -11,9 +11,14 @@
11
11
  #error "THE_SIMD_LEVEL must be defined before including IVFPQScanner_impl.h"
12
12
  #endif
13
13
 
14
+ #include <algorithm>
15
+ #include <cstring>
16
+ #include <type_traits>
17
+
14
18
  #include <faiss/IndexIVFPQ.h>
15
19
  #include <faiss/impl/IDSelector.h>
16
20
  #include <faiss/impl/ResultHandler.h>
21
+ #include <faiss/impl/platform_macros.h>
17
22
  #include <faiss/impl/pq_code_distance/IVFPQ_QueryTables.h>
18
23
  #include <faiss/impl/pq_code_distance/pq_code_distance-inl.h>
19
24
  #include <faiss/impl/simd_dispatch.h>
@@ -70,6 +75,48 @@ struct WrappedSearchResult {
70
75
  }
71
76
  };
72
77
 
78
+ /** For each sub-quantizer, a block of codes reads one 1 KB table slice, which
79
+ * stays in L1; code by code, a table larger than L1 makes every lookup an L1
80
+ * miss. SL as in PQCodeDistanceScalar. */
81
+ template <SIMDLevel SL>
82
+ void pq_distances_8bit_by_block(
83
+ size_t M,
84
+ const float* sim_table,
85
+ float dis0,
86
+ size_t n,
87
+ const uint8_t* codes,
88
+ float* distances) {
89
+ constexpr size_t kBlock = 64;
90
+ constexpr size_t ksub = PQCodeDistanceScalar8<SL>::ksub;
91
+ for (size_t j0 = 0; j0 < n; j0 += kBlock) {
92
+ const size_t nb = std::min(kBlock, n - j0);
93
+ const uint8_t* block = codes + j0 * M;
94
+ float* acc = distances + j0;
95
+ std::fill(acc, acc + nb, 0.0f);
96
+ const float* tab = sim_table;
97
+ size_t m = 0;
98
+ for (; m + 4 <= M; m += 4, tab += 4 * ksub) {
99
+ const uint8_t* c = block + m;
100
+ for (size_t b = 0; b < nb; b++) {
101
+ uint32_t w;
102
+ memcpy(&w, c + b * M, sizeof(w));
103
+ acc[b] += (tab[w & 255] + tab[ksub + ((w >> 8) & 255)]) +
104
+ (tab[2 * ksub + ((w >> 16) & 255)] +
105
+ tab[3 * ksub + (w >> 24)]);
106
+ }
107
+ }
108
+ for (; m < M; m++, tab += ksub) {
109
+ const uint8_t* c = block + m;
110
+ for (size_t b = 0; b < nb; b++) {
111
+ acc[b] += tab[c[b * M]];
112
+ }
113
+ }
114
+ for (size_t b = 0; b < nb; b++) {
115
+ acc[b] += dis0;
116
+ }
117
+ }
118
+ }
119
+
73
120
  /*****************************************************
74
121
  * Scaning the codes.
75
122
  * The scanning functions call their favorite precompute_*
@@ -411,10 +458,8 @@ struct IVFPQScannerT : QueryTables {
411
458
  }
412
459
  }
413
460
 
414
- #pragma omp critical
415
- {
416
- indexIVFPQ_stats.n_hamming_pass += n_hamming_pass;
417
- }
461
+ detail::atomic_fetch_add_relaxed(
462
+ indexIVFPQ_stats.n_hamming_pass, n_hamming_pass);
418
463
  }
419
464
 
420
465
  template <class SearchResultType>
@@ -487,6 +532,29 @@ struct IVFPQScanner : IVFPQScannerT<idx_t, METRIC_TYPE, PQCodeDist>,
487
532
  this->pq.M, this->pq.nbits, this->sim_table, code);
488
533
  }
489
534
 
535
+ void distances_to_codes(size_t n, const uint8_t* codes, float* distances)
536
+ const override {
537
+ // Where gathers are fast (Intel), the block kernel is faster at
538
+ // M <= 64, and the per-code gather kernels are faster at M = 128
539
+ // unless all cores are busy.
540
+ if constexpr (
541
+ has_scalar_8bit_kernel<THE_SIMD_LEVEL>() &&
542
+ std::is_same_v<typename PQCodeDist::PQDecoder, PQDecoder8>) {
543
+ if (precompute_mode == 2 &&
544
+ (SIMDConfig::scalar_gather || this->pq.M <= 64)) {
545
+ pq_distances_8bit_by_block<THE_SIMD_LEVEL>(
546
+ this->pq.M,
547
+ this->sim_table,
548
+ this->dis0,
549
+ n,
550
+ codes,
551
+ distances);
552
+ return;
553
+ }
554
+ }
555
+ InvertedListScanner::distances_to_codes(n, codes, distances);
556
+ }
557
+
490
558
  size_t scan_codes(
491
559
  size_t ncode,
492
560
  const uint8_t* codes,
@@ -560,6 +628,13 @@ InvertedListScanner* make_IVFPQInvertedListScanner<THE_SIMD_LEVEL>(
560
628
 
561
629
  auto with_decoder = [&]<bool use_sel>() -> InvertedListScanner* {
562
630
  if (ivfpq.pq.nbits == 8) {
631
+ if constexpr (has_scalar_8bit_kernel<THE_SIMD_LEVEL>()) {
632
+ if (use_scalar_8bit_kernel<THE_SIMD_LEVEL>(ivfpq.pq.M)) {
633
+ return make.template operator()<
634
+ PQCodeDistanceScalar8Dist<THE_SIMD_LEVEL>,
635
+ use_sel>();
636
+ }
637
+ }
563
638
  return make.template
564
639
  operator()<PQCodeDistance<PQDecoder8, THE_SIMD_LEVEL>, use_sel>();
565
640
  } else if (ivfpq.pq.nbits == 16) {
@@ -102,6 +102,12 @@ template <>
102
102
  FlatCodesDistanceComputer* get_PQFlatCodesDistanceComputer<THE_SIMD_LEVEL>(
103
103
  const IndexPQ& index) {
104
104
  if (index.pq.nbits == 8) {
105
+ if constexpr (has_scalar_8bit_kernel<THE_SIMD_LEVEL>()) {
106
+ if (use_scalar_8bit_kernel<THE_SIMD_LEVEL>(index.pq.M)) {
107
+ return new PQDistanceComputer<
108
+ PQCodeDistanceScalar8Dist<THE_SIMD_LEVEL>>(index);
109
+ }
110
+ }
105
111
  return new PQDistanceComputer<
106
112
  PQCodeDistance<PQDecoder8, THE_SIMD_LEVEL>>(index);
107
113
  } else if (index.pq.nbits == 16) {
@@ -5,8 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- #ifdef COMPILE_SIMD_AVX2
9
-
10
8
  #define THE_SIMD_LEVEL SIMDLevel::AVX2
11
9
 
12
10
  // NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
@@ -19,5 +17,3 @@
19
17
  #include <faiss/impl/pq_code_distance/PQDistanceComputer_impl.h>
20
18
  // NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
21
19
  #include <faiss/impl/pq_code_distance/IVFPQScanner_impl.h>
22
-
23
- #endif // COMPILE_SIMD_AVX2
@@ -5,8 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- #ifdef COMPILE_SIMD_AVX512
9
-
10
8
  #define THE_SIMD_LEVEL SIMDLevel::AVX512
11
9
 
12
10
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
@@ -19,5 +17,3 @@
19
17
  #include <faiss/impl/pq_code_distance/PQDistanceComputer_impl.h>
20
18
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
21
19
  #include <faiss/impl/pq_code_distance/IVFPQScanner_impl.h>
22
-
23
- #endif // COMPILE_SIMD_AVX512
@@ -5,8 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- #ifdef COMPILE_SIMD_ARM_NEON
9
-
10
8
  #define THE_SIMD_LEVEL SIMDLevel::ARM_NEON
11
9
 
12
10
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
@@ -19,5 +17,3 @@
19
17
  #include <faiss/impl/pq_code_distance/PQDistanceComputer_impl.h>
20
18
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
21
19
  #include <faiss/impl/pq_code_distance/IVFPQScanner_impl.h>
22
-
23
- #endif // COMPILE_SIMD_ARM_NEON
@@ -160,6 +160,10 @@ inline void distance_four_codes_avx2_pqdecoder8_m8(
160
160
  namespace faiss {
161
161
  namespace pq_code_distance {
162
162
 
163
+ // On AMD Zen 3/4/5 (SIMDConfig::scalar_gather) the scalar kernel is 0-48%
164
+ // faster than these gathers at M = 8-384; on Intel the gathers are faster.
165
+ // The callers select it with use_scalar_8bit_kernel().
166
+
163
167
  // NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
164
168
  template <>
165
169
  float pq_code_distance_8bit_single_impl<SIMDLevel::AVX2>(