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
@@ -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
  #include <faiss/utils/rabitq_simd.h>
11
9
  #include <immintrin.h>
12
10
  #include <limits>
@@ -378,9 +376,11 @@ uint64_t bitwise_and_dot_product<SIMDLevel::AVX512>(
378
376
  }
379
377
  sum += reduce_add_128(sum_128);
380
378
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
381
- const auto yv = *(const uint64_t*)(data + offset);
379
+ uint64_t yv;
380
+ std::memcpy(&yv, data + offset, sizeof(yv));
382
381
  for (int j = 0; j < qb; j++) {
383
- const auto qv = *(const uint64_t*)(query + j * size + offset);
382
+ uint64_t qv;
383
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
384
384
  sum += popcount64(qv & yv) << j;
385
385
  }
386
386
  }
@@ -457,10 +457,12 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
457
457
  dot_product += reduce_add_128(dot_128);
458
458
  popcount_sum += reduce_add_128(pop_128);
459
459
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
460
- const auto yv = *(const uint64_t*)(data + offset);
460
+ uint64_t yv;
461
+ std::memcpy(&yv, data + offset, sizeof(yv));
461
462
  popcount_sum += popcount64(yv);
462
463
  for (int j = 0; j < qb; j++) {
463
- const auto qv = *(const uint64_t*)(query + j * size + offset);
464
+ uint64_t qv;
465
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
464
466
  dot_product += popcount64(qv & yv) << j;
465
467
  }
466
468
  }
@@ -527,9 +529,11 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::AVX512>(
527
529
  }
528
530
  sum += reduce_add_128(sum_128);
529
531
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
530
- const auto yv = *(const uint64_t*)(data + offset);
532
+ uint64_t yv;
533
+ std::memcpy(&yv, data + offset, sizeof(yv));
531
534
  for (int j = 0; j < qb; j++) {
532
- const auto qv = *(const uint64_t*)(query + j * size + offset);
535
+ uint64_t qv;
536
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
533
537
  sum += popcount64(qv ^ yv) << j;
534
538
  }
535
539
  }
@@ -572,7 +576,8 @@ uint64_t popcount<SIMDLevel::AVX512>(const uint8_t* data, size_t size) {
572
576
  }
573
577
  sum += reduce_add_128(sum_128);
574
578
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
575
- const auto yv = *(const uint64_t*)(data + offset);
579
+ uint64_t yv;
580
+ std::memcpy(&yv, data + offset, sizeof(yv));
576
581
  sum += popcount64(yv);
577
582
  }
578
583
  for (; offset < size; ++offset) {
@@ -654,13 +659,9 @@ inline float ip_1exbit_avx512(
654
659
  return result;
655
660
  }
656
661
 
657
- // Needs BMI2 for _pext_u64. Some AVX2 CPUs lack it, and FAISS_BMI2_FLAGS can
658
- // be empty, so the dispatcher falls back to the scalar path without it.
659
- #ifdef __BMI2__
660
- // Bitplane kernel for ex_bits >= 2, 16 dims per iteration. A bitplane is
661
- // already a bitmask, so it goes into a mask register and one masked add
662
- // applies its weight. Reads of ex_code run a few bytes past the ex-code
663
- // section into the record's own trailing factors, so they stay in bounds.
662
+ // Bit-plane kernel for ex_bits >= 2. It scores 16 dims per pass.
663
+ // Each plane acts as a mask for one weighted add. Reads can run
664
+ // past the codes into the row tail, which stays in bounds.
664
665
  inline float ip_bitplane_avx512(
665
666
  const uint8_t* __restrict sign_bits,
666
667
  const uint8_t* __restrict ex_code,
@@ -737,7 +738,6 @@ inline float ip_bitplane_avx512(
737
738
  result += ip_scalar(sign_bits, ex_code, rotated_q, i, d, ex_bits, cb);
738
739
  return result;
739
740
  }
740
- #endif // __BMI2__
741
741
 
742
742
  } // namespace
743
743
 
@@ -749,19 +749,36 @@ float compute_inner_product<SIMDLevel::AVX512>(
749
749
  size_t d,
750
750
  size_t ex_bits,
751
751
  float cb) {
752
+ if (ex_bits == 8) {
753
+ // RBQ9 has one byte per extra code: no bit-plane extraction or BMI2.
754
+ __m512 acc = _mm512_setzero_ps();
755
+ const __m512 weight = _mm512_set1_ps(256.f);
756
+ const __m512 offset = _mm512_set1_ps(cb);
757
+ size_t i = 0;
758
+ for (; i + 16 <= d; i += 16) {
759
+ uint16_t signs;
760
+ memcpy(&signs, sign_bits + i / 8, sizeof(signs));
761
+ const __m128i bytes = _mm_loadu_si128(
762
+ reinterpret_cast<const __m128i*>(ex_code + i));
763
+ __m512 recon = _mm512_cvtepi32_ps(_mm512_cvtepu8_epi32(bytes));
764
+ recon = _mm512_mask_add_ps(recon, signs, recon, weight);
765
+ acc = _mm512_fmadd_ps(
766
+ _mm512_loadu_ps(rotated_q + i),
767
+ _mm512_add_ps(recon, offset),
768
+ acc);
769
+ }
770
+ return _mm512_reduce_add_ps(acc) +
771
+ ip_scalar(sign_bits, ex_code, rotated_q, i, d, ex_bits, cb);
772
+ }
752
773
  if (ex_bits == 1) {
753
774
  return ip_1exbit_avx512(sign_bits, ex_code, rotated_q, d, cb);
754
775
  }
755
776
 
756
- #ifdef __BMI2__
757
777
  if (ex_bits <= 7) {
758
778
  return ip_bitplane_avx512(
759
779
  sign_bits, ex_code, rotated_q, d, ex_bits, cb);
760
780
  }
761
- #endif
762
781
  return ip_scalar(sign_bits, ex_code, rotated_q, 0, d, ex_bits, cb);
763
782
  }
764
783
 
765
784
  } // namespace faiss::rabitq::multibit
766
-
767
- #endif // COMPILE_SIMD_AVX512
@@ -30,8 +30,6 @@
30
30
  * the AVX512 implementation to avoid duplicating that code path.
31
31
  */
32
32
 
33
- #ifdef COMPILE_SIMD_AVX512_VPOPCNT
34
-
35
33
  #include <faiss/utils/popcount.h>
36
34
  #include <faiss/utils/rabitq_simd.h>
37
35
  #include <immintrin.h>
@@ -63,6 +61,43 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::AVX512>(
63
61
  template <>
64
62
  uint64_t popcount<SIMDLevel::AVX512>(const uint8_t* data, size_t size);
65
63
 
64
+ template <>
65
+ void bitwise_q4_batch_4<SIMDLevel::AVX512_VPOPCNT>(
66
+ const uint8_t* query,
67
+ const uint8_t* const* data,
68
+ size_t size,
69
+ BitwiseAndDotProductResult* results) {
70
+ __m512i dots[4], pops[4];
71
+ for (int i = 0; i < 4; ++i) {
72
+ dots[i] = pops[i] = _mm512_setzero_si512();
73
+ }
74
+ for (size_t off = 0; off < size; off += 64) {
75
+ const size_t count = std::min(size - off, size_t(64));
76
+ const __mmask64 mask =
77
+ count == 64 ? ~__mmask64(0) : (__mmask64(1) << count) - 1;
78
+ __m512i x[4];
79
+ for (int i = 0; i < 4; ++i) {
80
+ x[i] = _mm512_maskz_loadu_epi8(mask, data[i] + off);
81
+ pops[i] = _mm512_add_epi64(pops[i], _mm512_popcnt_epi64(x[i]));
82
+ }
83
+ for (int bit = 0; bit < 4; ++bit) {
84
+ // Load each query plane once for four independent database codes.
85
+ const __m512i q =
86
+ _mm512_maskz_loadu_epi8(mask, query + bit * size + off);
87
+ for (int i = 0; i < 4; ++i) {
88
+ const __m512i p =
89
+ _mm512_popcnt_epi64(_mm512_and_si512(q, x[i]));
90
+ dots[i] = _mm512_add_epi64(dots[i], _mm512_slli_epi64(p, bit));
91
+ }
92
+ }
93
+ }
94
+ for (int i = 0; i < 4; ++i) {
95
+ results[i] = {
96
+ static_cast<uint64_t>(_mm512_reduce_add_epi64(dots[i])),
97
+ static_cast<uint64_t>(_mm512_reduce_add_epi64(pops[i]))};
98
+ }
99
+ }
100
+
66
101
  namespace {
67
102
 
68
103
  // 512-bit popcount using AVX-512 VPOPCNTDQ (vpopcntq).
@@ -164,10 +199,11 @@ uint64_t bitwise_and_dot_product<SIMDLevel::AVX512_VPOPCNT>(
164
199
 
165
200
  // 64-bit scalar tail.
166
201
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
167
- const auto yv = *reinterpret_cast<const uint64_t*>(data + offset);
202
+ uint64_t yv;
203
+ std::memcpy(&yv, data + offset, sizeof(yv));
168
204
  for (size_t j = 0; j < qb; j++) {
169
- const auto qv = *reinterpret_cast<const uint64_t*>(
170
- query + j * size + offset);
205
+ uint64_t qv;
206
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
171
207
  sum += static_cast<uint64_t>(popcount64(qv & yv)) << j;
172
208
  }
173
209
  }
@@ -255,11 +291,12 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
255
291
  popcount_sum += reduce_add_128(pop_128);
256
292
 
257
293
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
258
- const auto yv = *reinterpret_cast<const uint64_t*>(data + offset);
294
+ uint64_t yv;
295
+ std::memcpy(&yv, data + offset, sizeof(yv));
259
296
  popcount_sum += popcount64(yv);
260
297
  for (size_t j = 0; j < qb; j++) {
261
- const auto qv = *reinterpret_cast<const uint64_t*>(
262
- query + j * size + offset);
298
+ uint64_t qv;
299
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
263
300
  dot_product += static_cast<uint64_t>(popcount64(qv & yv)) << j;
264
301
  }
265
302
  }
@@ -336,10 +373,11 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::AVX512_VPOPCNT>(
336
373
  sum += reduce_add_128(sum_128);
337
374
 
338
375
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
339
- const auto yv = *reinterpret_cast<const uint64_t*>(data + offset);
376
+ uint64_t yv;
377
+ std::memcpy(&yv, data + offset, sizeof(yv));
340
378
  for (size_t j = 0; j < qb; j++) {
341
- const auto qv = *reinterpret_cast<const uint64_t*>(
342
- query + j * size + offset);
379
+ uint64_t qv;
380
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
343
381
  sum += static_cast<uint64_t>(popcount64(qv ^ yv)) << j;
344
382
  }
345
383
  }
@@ -389,7 +427,8 @@ uint64_t popcount<SIMDLevel::AVX512_VPOPCNT>(const uint8_t* data, size_t size) {
389
427
  sum += reduce_add_128(sum_128);
390
428
 
391
429
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
392
- const auto yv = *reinterpret_cast<const uint64_t*>(data + offset);
430
+ uint64_t yv;
431
+ std::memcpy(&yv, data + offset, sizeof(yv));
393
432
  sum += popcount64(yv);
394
433
  }
395
434
  for (; offset < size; ++offset) {
@@ -428,5 +467,3 @@ float compute_inner_product<SIMDLevel::AVX512_VPOPCNT>(
428
467
  }
429
468
 
430
469
  } // namespace faiss::rabitq::multibit
431
-
432
- #endif // COMPILE_SIMD_AVX512_VPOPCNT
@@ -7,17 +7,78 @@
7
7
 
8
8
  #include <faiss/utils/rabitq_simd.h>
9
9
 
10
- #ifdef COMPILE_SIMD_ARM_NEON
10
+ #include <arm_neon.h>
11
+
12
+ #include <array>
13
+
14
+ #include <faiss/impl/FaissAssert.h>
11
15
 
12
16
  namespace faiss::rabitq {
13
17
 
18
+ namespace {
19
+
20
+ // One accumulator per query bit plane. RaBitQuantizer caps qb at 8, so the
21
+ // accumulator arrays below are fixed size rather than heap allocated.
22
+ constexpr size_t kMaxQueryBits = 8;
23
+
24
+ inline uint32x4_t accumulate_popcount(uint32x4_t acc, uint8x16_t value) {
25
+ const uint16x8_t pair_counts = vpaddlq_u8(vcntq_u8(value));
26
+ return vpadalq_u16(acc, pair_counts);
27
+ }
28
+
29
+ inline uint64_t reduce_popcount(uint32x4_t acc) {
30
+ return vaddlvq_u32(acc);
31
+ }
32
+
33
+ } // namespace
34
+
14
35
  template <>
15
36
  uint64_t bitwise_and_dot_product<SIMDLevel::ARM_NEON>(
16
37
  const uint8_t* query,
17
38
  const uint8_t* data,
18
39
  size_t size,
19
40
  size_t qb) {
20
- return bitwise_and_dot_product<SIMDLevel::NONE>(query, data, size, qb);
41
+ FAISS_THROW_IF_NOT(qb <= kMaxQueryBits);
42
+ std::array<uint32x4_t, kMaxQueryBits> accumulators;
43
+ for (size_t j = 0; j < qb; j++) {
44
+ accumulators[j] = vdupq_n_u32(0);
45
+ }
46
+
47
+ size_t offset = 0;
48
+ for (; offset + 16 <= size; offset += 16) {
49
+ const uint8x16_t value = vld1q_u8(data + offset);
50
+ for (size_t j = 0; j < qb; j++) {
51
+ const uint8x16_t query_value = vld1q_u8(query + j * size + offset);
52
+ accumulators[j] = accumulate_popcount(
53
+ accumulators[j], vandq_u8(query_value, value));
54
+ }
55
+ }
56
+
57
+ uint64_t result = 0;
58
+ for (size_t j = 0; j < qb; j++) {
59
+ result += reduce_popcount(accumulators[j]) << j;
60
+ }
61
+ for (; offset + 8 <= size; offset += 8) {
62
+ uint64_t value;
63
+ memcpy(&value, data + offset, sizeof(value));
64
+ for (size_t j = 0; j < qb; j++) {
65
+ uint64_t query_value;
66
+ memcpy(&query_value,
67
+ query + j * size + offset,
68
+ sizeof(query_value));
69
+ result += static_cast<uint64_t>(popcount64(query_value & value))
70
+ << j;
71
+ }
72
+ }
73
+ for (; offset < size; offset++) {
74
+ const uint8_t value = data[offset];
75
+ for (size_t j = 0; j < qb; j++) {
76
+ result += static_cast<uint64_t>(
77
+ popcount32(query[j * size + offset] & value))
78
+ << j;
79
+ }
80
+ }
81
+ return result;
21
82
  }
22
83
 
23
84
  template <>
@@ -27,8 +88,52 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
27
88
  const uint8_t* data,
28
89
  size_t size,
29
90
  size_t qb) {
30
- return bitwise_and_dot_product_with_popcount<SIMDLevel::NONE>(
31
- query, data, size, qb);
91
+ FAISS_THROW_IF_NOT(qb <= kMaxQueryBits);
92
+ std::array<uint32x4_t, kMaxQueryBits> dot_accumulators;
93
+ for (size_t j = 0; j < qb; j++) {
94
+ dot_accumulators[j] = vdupq_n_u32(0);
95
+ }
96
+ uint32x4_t popcount_accumulator = vdupq_n_u32(0);
97
+
98
+ size_t offset = 0;
99
+ for (; offset + 16 <= size; offset += 16) {
100
+ const uint8x16_t value = vld1q_u8(data + offset);
101
+ popcount_accumulator = accumulate_popcount(popcount_accumulator, value);
102
+ for (size_t j = 0; j < qb; j++) {
103
+ const uint8x16_t query_value = vld1q_u8(query + j * size + offset);
104
+ dot_accumulators[j] = accumulate_popcount(
105
+ dot_accumulators[j], vandq_u8(query_value, value));
106
+ }
107
+ }
108
+
109
+ uint64_t dot_product = 0;
110
+ for (size_t j = 0; j < qb; j++) {
111
+ dot_product += reduce_popcount(dot_accumulators[j]) << j;
112
+ }
113
+ uint64_t popcount_sum = reduce_popcount(popcount_accumulator);
114
+ for (; offset + 8 <= size; offset += 8) {
115
+ uint64_t value;
116
+ memcpy(&value, data + offset, sizeof(value));
117
+ popcount_sum += popcount64(value);
118
+ for (size_t j = 0; j < qb; j++) {
119
+ uint64_t query_value;
120
+ memcpy(&query_value,
121
+ query + j * size + offset,
122
+ sizeof(query_value));
123
+ dot_product +=
124
+ static_cast<uint64_t>(popcount64(query_value & value)) << j;
125
+ }
126
+ }
127
+ for (; offset < size; offset++) {
128
+ const uint8_t value = data[offset];
129
+ popcount_sum += popcount32(value);
130
+ for (size_t j = 0; j < qb; j++) {
131
+ dot_product += static_cast<uint64_t>(
132
+ popcount32(query[j * size + offset] & value))
133
+ << j;
134
+ }
135
+ }
136
+ return {dot_product, popcount_sum};
32
137
  }
33
138
 
34
139
  template <>
@@ -37,18 +142,185 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::ARM_NEON>(
37
142
  const uint8_t* data,
38
143
  size_t size,
39
144
  size_t qb) {
40
- return bitwise_xor_dot_product<SIMDLevel::NONE>(query, data, size, qb);
145
+ FAISS_THROW_IF_NOT(qb <= kMaxQueryBits);
146
+ std::array<uint32x4_t, kMaxQueryBits> accumulators;
147
+ for (size_t j = 0; j < qb; j++) {
148
+ accumulators[j] = vdupq_n_u32(0);
149
+ }
150
+
151
+ size_t offset = 0;
152
+ for (; offset + 16 <= size; offset += 16) {
153
+ const uint8x16_t value = vld1q_u8(data + offset);
154
+ for (size_t j = 0; j < qb; j++) {
155
+ const uint8x16_t query_value = vld1q_u8(query + j * size + offset);
156
+ accumulators[j] = accumulate_popcount(
157
+ accumulators[j], veorq_u8(query_value, value));
158
+ }
159
+ }
160
+
161
+ uint64_t result = 0;
162
+ for (size_t j = 0; j < qb; j++) {
163
+ result += reduce_popcount(accumulators[j]) << j;
164
+ }
165
+ for (; offset + 8 <= size; offset += 8) {
166
+ uint64_t value;
167
+ memcpy(&value, data + offset, sizeof(value));
168
+ for (size_t j = 0; j < qb; j++) {
169
+ uint64_t query_value;
170
+ memcpy(&query_value,
171
+ query + j * size + offset,
172
+ sizeof(query_value));
173
+ result += static_cast<uint64_t>(popcount64(query_value ^ value))
174
+ << j;
175
+ }
176
+ }
177
+ for (; offset < size; offset++) {
178
+ const uint8_t value = data[offset];
179
+ for (size_t j = 0; j < qb; j++) {
180
+ result += static_cast<uint64_t>(
181
+ popcount32(query[j * size + offset] ^ value))
182
+ << j;
183
+ }
184
+ }
185
+ return result;
41
186
  }
42
187
 
43
188
  template <>
44
189
  uint64_t popcount<SIMDLevel::ARM_NEON>(const uint8_t* data, size_t size) {
45
- return popcount<SIMDLevel::NONE>(data, size);
190
+ uint32x4_t accumulator = vdupq_n_u32(0);
191
+ size_t offset = 0;
192
+ for (; offset + 16 <= size; offset += 16) {
193
+ accumulator = accumulate_popcount(accumulator, vld1q_u8(data + offset));
194
+ }
195
+
196
+ uint64_t result = reduce_popcount(accumulator);
197
+ for (; offset + 8 <= size; offset += 8) {
198
+ uint64_t value;
199
+ memcpy(&value, data + offset, sizeof(value));
200
+ result += popcount64(value);
201
+ }
202
+ for (; offset < size; offset++) {
203
+ result += popcount32(data[offset]);
204
+ }
205
+ return result;
46
206
  }
47
207
 
48
208
  } // namespace faiss::rabitq
49
209
 
50
210
  namespace faiss::rabitq::multibit {
51
211
 
212
+ namespace {
213
+
214
+ inline float horizontal_sum(float32x4_t low, float32x4_t high) {
215
+ return vaddvq_f32(vaddq_f32(low, high));
216
+ }
217
+
218
+ inline float ip_1exbit_neon(
219
+ const uint8_t* __restrict sign_bits,
220
+ const uint8_t* __restrict ex_code,
221
+ const float* __restrict rotated_q,
222
+ size_t d,
223
+ float cb) {
224
+ const uint32x4_t low_bit_positions = {1, 2, 4, 8};
225
+ const uint32x4_t high_bit_positions = {16, 32, 64, 128};
226
+ const uint32x4_t sign_weight = vdupq_n_u32(2);
227
+ const uint32x4_t ex_weight = vdupq_n_u32(1);
228
+ const float32x4_t bias = vdupq_n_f32(cb);
229
+ float32x4_t low_accumulator = vdupq_n_f32(0.0f);
230
+ float32x4_t high_accumulator = vdupq_n_f32(0.0f);
231
+
232
+ size_t i = 0;
233
+ for (; i + 8 <= d; i += 8) {
234
+ const uint32x4_t sign = vdupq_n_u32(sign_bits[i / 8]);
235
+ const uint32x4_t extra = vdupq_n_u32(ex_code[i / 8]);
236
+
237
+ const uint32x4_t low_values = vaddq_u32(
238
+ vandq_u32(vtstq_u32(sign, low_bit_positions), sign_weight),
239
+ vandq_u32(vtstq_u32(extra, low_bit_positions), ex_weight));
240
+ const uint32x4_t high_values = vaddq_u32(
241
+ vandq_u32(vtstq_u32(sign, high_bit_positions), sign_weight),
242
+ vandq_u32(vtstq_u32(extra, high_bit_positions), ex_weight));
243
+
244
+ const float32x4_t low_reconstruction =
245
+ vaddq_f32(vcvtq_f32_u32(low_values), bias);
246
+ const float32x4_t high_reconstruction =
247
+ vaddq_f32(vcvtq_f32_u32(high_values), bias);
248
+ low_accumulator = vfmaq_f32(
249
+ low_accumulator, vld1q_f32(rotated_q + i), low_reconstruction);
250
+ high_accumulator = vfmaq_f32(
251
+ high_accumulator,
252
+ vld1q_f32(rotated_q + i + 4),
253
+ high_reconstruction);
254
+ }
255
+
256
+ float result = horizontal_sum(low_accumulator, high_accumulator);
257
+ result += ip_scalar(sign_bits, ex_code, rotated_q, i, d, 1, cb);
258
+ return result;
259
+ }
260
+
261
+ template <size_t ExBits>
262
+ inline float ip_multibit_neon(
263
+ const uint8_t* __restrict sign_bits,
264
+ const uint8_t* __restrict ex_code,
265
+ const float* __restrict rotated_q,
266
+ size_t d,
267
+ float cb) {
268
+ static_assert(ExBits >= 2 && ExBits <= 7);
269
+ const uint32x4_t low_bit_positions = {1, 2, 4, 8};
270
+ const uint32x4_t high_bit_positions = {16, 32, 64, 128};
271
+ const uint32x4_t sign_weight =
272
+ vdupq_n_u32(static_cast<uint32_t>(1u << ExBits));
273
+ const uint64x2_t code_mask =
274
+ vdupq_n_u64(static_cast<uint64_t>((1u << ExBits) - 1));
275
+ constexpr int64_t bit_width = static_cast<int64_t>(ExBits);
276
+ const int64x2_t shifts_01 = {0, -bit_width};
277
+ const int64x2_t shifts_23 = {-2 * bit_width, -3 * bit_width};
278
+ const int64x2_t shifts_45 = {-4 * bit_width, -5 * bit_width};
279
+ const int64x2_t shifts_67 = {-6 * bit_width, -7 * bit_width};
280
+ const float32x4_t bias = vdupq_n_f32(cb);
281
+ float32x4_t low_accumulator = vdupq_n_f32(0.0f);
282
+ float32x4_t high_accumulator = vdupq_n_f32(0.0f);
283
+
284
+ size_t i = 0;
285
+ for (; i + 8 <= d; i += 8) {
286
+ uint64_t packed_codes = 0;
287
+ memcpy(&packed_codes, ex_code + (i / 8) * ExBits, ExBits);
288
+ const uint64x2_t packed = vdupq_n_u64(packed_codes);
289
+
290
+ const uint32x4_t low_codes = vcombine_u32(
291
+ vmovn_u64(vandq_u64(vshlq_u64(packed, shifts_01), code_mask)),
292
+ vmovn_u64(vandq_u64(vshlq_u64(packed, shifts_23), code_mask)));
293
+ const uint32x4_t high_codes = vcombine_u32(
294
+ vmovn_u64(vandq_u64(vshlq_u64(packed, shifts_45), code_mask)),
295
+ vmovn_u64(vandq_u64(vshlq_u64(packed, shifts_67), code_mask)));
296
+
297
+ const uint32x4_t sign = vdupq_n_u32(sign_bits[i / 8]);
298
+ const uint32x4_t low_values = vaddq_u32(
299
+ low_codes,
300
+ vandq_u32(vtstq_u32(sign, low_bit_positions), sign_weight));
301
+ const uint32x4_t high_values = vaddq_u32(
302
+ high_codes,
303
+ vandq_u32(vtstq_u32(sign, high_bit_positions), sign_weight));
304
+
305
+ const float32x4_t low_reconstruction =
306
+ vaddq_f32(vcvtq_f32_u32(low_values), bias);
307
+ const float32x4_t high_reconstruction =
308
+ vaddq_f32(vcvtq_f32_u32(high_values), bias);
309
+ low_accumulator = vfmaq_f32(
310
+ low_accumulator, vld1q_f32(rotated_q + i), low_reconstruction);
311
+ high_accumulator = vfmaq_f32(
312
+ high_accumulator,
313
+ vld1q_f32(rotated_q + i + 4),
314
+ high_reconstruction);
315
+ }
316
+
317
+ float result = horizontal_sum(low_accumulator, high_accumulator);
318
+ result += ip_scalar(sign_bits, ex_code, rotated_q, i, d, ExBits, cb);
319
+ return result;
320
+ }
321
+
322
+ } // namespace
323
+
52
324
  template <>
53
325
  float compute_inner_product<SIMDLevel::ARM_NEON>(
54
326
  const uint8_t* __restrict sign_bits,
@@ -57,10 +329,25 @@ float compute_inner_product<SIMDLevel::ARM_NEON>(
57
329
  size_t d,
58
330
  size_t ex_bits,
59
331
  float cb) {
60
- return compute_inner_product<SIMDLevel::NONE>(
61
- sign_bits, ex_code, rotated_q, d, ex_bits, cb);
332
+ if (ex_bits == 1) {
333
+ return ip_1exbit_neon(sign_bits, ex_code, rotated_q, d, cb);
334
+ }
335
+ switch (ex_bits) {
336
+ case 2:
337
+ return ip_multibit_neon<2>(sign_bits, ex_code, rotated_q, d, cb);
338
+ case 3:
339
+ return ip_multibit_neon<3>(sign_bits, ex_code, rotated_q, d, cb);
340
+ case 4:
341
+ return ip_multibit_neon<4>(sign_bits, ex_code, rotated_q, d, cb);
342
+ case 5:
343
+ return ip_multibit_neon<5>(sign_bits, ex_code, rotated_q, d, cb);
344
+ case 6:
345
+ return ip_multibit_neon<6>(sign_bits, ex_code, rotated_q, d, cb);
346
+ case 7:
347
+ return ip_multibit_neon<7>(sign_bits, ex_code, rotated_q, d, cb);
348
+ default:
349
+ return ip_scalar(sign_bits, ex_code, rotated_q, 0, d, ex_bits, cb);
350
+ }
62
351
  }
63
352
 
64
353
  } // namespace faiss::rabitq::multibit
65
-
66
- #endif // COMPILE_SIMD_ARM_NEON
@@ -9,8 +9,6 @@
9
9
 
10
10
  #include <faiss/utils/rabitq_simd.h>
11
11
 
12
- #ifdef COMPILE_SIMD_RISCV_RVV
13
-
14
12
  #include <riscv_vector.h>
15
13
 
16
14
  namespace faiss::rabitq {
@@ -188,5 +186,3 @@ compute_inner_product<SIMDLevel::RISCV_RVV>(
188
186
  }
189
187
 
190
188
  } // namespace faiss::rabitq::multibit
191
-
192
- #endif // COMPILE_SIMD_RISCV_RVV
@@ -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
  #include <faiss/utils/simd_impl/super_kmeans_kernels.h>
11
9
 
12
10
  #include <immintrin.h>
@@ -53,5 +51,3 @@ float block_l2<SIMDLevel::AVX2>(const float* x, const float* y, int n) {
53
51
 
54
52
  } // namespace detail
55
53
  } // namespace faiss
56
-
57
- #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
  #include <faiss/utils/simd_impl/super_kmeans_kernels.h>
11
9
 
12
10
  #include <immintrin.h>
@@ -41,5 +39,3 @@ float block_l2<SIMDLevel::AVX512>(const float* x, const float* y, int n) {
41
39
 
42
40
  } // namespace detail
43
41
  } // namespace faiss
44
-
45
- #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_SVE
9
-
10
8
  #include <faiss/utils/simd_impl/super_kmeans_kernels.h>
11
9
 
12
10
  #include <arm_sve.h>
@@ -30,5 +28,3 @@ float block_l2<SIMDLevel::ARM_SVE>(const float* x, const float* y, int n) {
30
28
 
31
29
  } // namespace detail
32
30
  } // namespace faiss
33
-
34
- #endif // COMPILE_SIMD_ARM_SVE