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,666 +5,14 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- #ifdef COMPILE_SIMD_AVX512
9
-
10
- #include <faiss/impl/simdlib/simdlib_avx512.h>
11
-
12
- #include <cstring>
13
-
14
- #include <faiss/impl/scalar_quantizer/codecs.h>
15
- #include <faiss/impl/scalar_quantizer/distance_computers.h>
16
- #include <faiss/impl/scalar_quantizer/quantizers.h>
17
- #include <faiss/impl/scalar_quantizer/scanners.h>
18
- #include <faiss/impl/scalar_quantizer/similarities.h>
8
+ #define THE_LEVEL_TO_DISPATCH SIMDLevel::AVX512
9
+ #include <faiss/impl/scalar_quantizer/sq-avx512-impl.h>
10
+ #include <faiss/utils/simd_impl/masked_sum-avx512.h>
19
11
 
20
12
  namespace faiss {
21
13
 
22
14
  namespace scalar_quantizer {
23
15
 
24
- using simd16float32 = faiss::simd16float32_tpl<SIMDLevel::AVX512>;
25
-
26
- namespace {
27
-
28
- FAISS_ALWAYS_INLINE uint16_t load_u16(const uint8_t* ptr) {
29
- uint16_t value;
30
- std::memcpy(&value, ptr, sizeof(value));
31
- return value;
32
- }
33
-
34
- FAISS_ALWAYS_INLINE uint32_t load_u32(const uint8_t* ptr) {
35
- uint32_t value;
36
- std::memcpy(&value, ptr, sizeof(value));
37
- return value;
38
- }
39
-
40
- FAISS_ALWAYS_INLINE uint64_t load_u64(const uint8_t* ptr) {
41
- uint64_t value;
42
- std::memcpy(&value, ptr, sizeof(value));
43
- return value;
44
- }
45
-
46
- FAISS_ALWAYS_INLINE uint32_t load_u24(const uint8_t* ptr) {
47
- return static_cast<uint32_t>(ptr[0]) |
48
- (static_cast<uint32_t>(ptr[1]) << 8) |
49
- (static_cast<uint32_t>(ptr[2]) << 16);
50
- }
51
-
52
- FAISS_ALWAYS_INLINE __m256i unpack_8x3bit_to_u32(uint32_t packed) {
53
- const __m256i shifts = _mm256_setr_epi32(0, 3, 6, 9, 12, 15, 18, 21);
54
- const __m256i indices =
55
- _mm256_srlv_epi32(_mm256_set1_epi32(packed), shifts);
56
- return _mm256_and_si256(indices, _mm256_set1_epi32(0x7));
57
- }
58
-
59
- FAISS_ALWAYS_INLINE __m512i unpack_16x1bit_to_u32(const uint8_t* code, int i) {
60
- const uint32_t packed = load_u16(code + (static_cast<size_t>(i) >> 3));
61
- const __m512i shifts = _mm512_setr_epi32(
62
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
63
- const __m512i indices =
64
- _mm512_srlv_epi32(_mm512_set1_epi32(packed), shifts);
65
- return _mm512_and_si512(indices, _mm512_set1_epi32(0x1));
66
- }
67
-
68
- FAISS_ALWAYS_INLINE __m512i unpack_16x2bit_to_u32(const uint8_t* code, int i) {
69
- const uint32_t packed = load_u32(code + (static_cast<size_t>(i) >> 2));
70
- const __m512i shifts = _mm512_setr_epi32(
71
- 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30);
72
- const __m512i indices =
73
- _mm512_srlv_epi32(_mm512_set1_epi32(packed), shifts);
74
- return _mm512_and_si512(indices, _mm512_set1_epi32(0x3));
75
- }
76
-
77
- FAISS_ALWAYS_INLINE __m512i unpack_16x3bit_to_u32(const uint8_t* code, int i) {
78
- const size_t byte_offset = (static_cast<size_t>(i) >> 4) * 6;
79
- const __m256i low = unpack_8x3bit_to_u32(load_u24(code + byte_offset));
80
- const __m256i high = unpack_8x3bit_to_u32(load_u24(code + byte_offset + 3));
81
- __m512i indices = _mm512_castsi256_si512(low);
82
- return _mm512_inserti32x8(indices, high, 1);
83
- }
84
-
85
- FAISS_ALWAYS_INLINE __m512i unpack_16x4bit_to_u32(const uint8_t* code, int i) {
86
- const uint64_t packed = load_u64(code + (static_cast<size_t>(i) >> 1));
87
- const __m256i shifts = _mm256_setr_epi32(0, 4, 8, 12, 16, 20, 24, 28);
88
- const __m256i low = _mm256_and_si256(
89
- _mm256_srlv_epi32(_mm256_set1_epi32((uint32_t)packed), shifts),
90
- _mm256_set1_epi32(0xf));
91
- const __m256i high = _mm256_and_si256(
92
- _mm256_srlv_epi32(
93
- _mm256_set1_epi32((uint32_t)(packed >> 32)), shifts),
94
- _mm256_set1_epi32(0xf));
95
- __m512i indices = _mm512_castsi256_si512(low);
96
- return _mm512_inserti32x8(indices, high, 1);
97
- }
98
-
99
- } // namespace
100
-
101
- /**********************************************************
102
- * Codecs
103
- **********************************************************/
104
-
105
- template <>
106
- struct Codec8bit<SIMDLevel::AVX512> : Codec8bit<SIMDLevel::NONE> {
107
- static FAISS_ALWAYS_INLINE simd16float32
108
- decode_16_components(const uint8_t* code, size_t i) {
109
- const __m128i c16 = _mm_loadu_si128((__m128i*)(code + i));
110
- const __m512i i32 = _mm512_cvtepu8_epi32(c16);
111
- const __m512 f16 = _mm512_cvtepi32_ps(i32);
112
- const __m512 half_one_255 = _mm512_set1_ps(0.5f / 255.f);
113
- const __m512 one_255 = _mm512_set1_ps(1.f / 255.f);
114
- return simd16float32(_mm512_fmadd_ps(f16, one_255, half_one_255));
115
- }
116
- };
117
-
118
- template <>
119
- struct Codec4bit<SIMDLevel::AVX512> : Codec4bit<SIMDLevel::NONE> {
120
- static FAISS_ALWAYS_INLINE simd16float32
121
- decode_16_components(const uint8_t* code, size_t i) {
122
- uint64_t c8 = *(uint64_t*)(code + (i >> 1));
123
- uint64_t mask = 0x0f0f0f0f0f0f0f0f;
124
- uint64_t c8ev = c8 & mask;
125
- uint64_t c8od = (c8 >> 4) & mask;
126
-
127
- __m128i c16 =
128
- _mm_unpacklo_epi8(_mm_set1_epi64x(c8ev), _mm_set1_epi64x(c8od));
129
- __m256i c8lo = _mm256_cvtepu8_epi32(c16);
130
- __m256i c8hi = _mm256_cvtepu8_epi32(_mm_srli_si128(c16, 8));
131
- __m512i i16 = _mm512_castsi256_si512(c8lo);
132
- i16 = _mm512_inserti32x8(i16, c8hi, 1);
133
- __m512 f16 = _mm512_cvtepi32_ps(i16);
134
- const __m512 half_one_255 = _mm512_set1_ps(0.5f / 15.f);
135
- const __m512 one_255 = _mm512_set1_ps(1.f / 15.f);
136
- return simd16float32(_mm512_fmadd_ps(f16, one_255, half_one_255));
137
- }
138
- };
139
-
140
- template <>
141
- struct Codec6bit<SIMDLevel::AVX512> : Codec6bit<SIMDLevel::NONE> {
142
- static FAISS_ALWAYS_INLINE simd16float32
143
- decode_16_components(const uint8_t* code, size_t i) {
144
- // pure AVX512 implementation (not necessarily the fastest).
145
- // see:
146
- // https://github.com/zilliztech/knowhere/blob/main/thirdparty/faiss/faiss/impl/ScalarQuantizerCodec_avx512.h
147
-
148
- // clang-format off
149
-
150
- // 16 components, 16x6 bit=12 bytes
151
- const __m128i bit_6v =
152
- _mm_maskz_loadu_epi8(0b0000111111111111, code + (i >> 2) * 3);
153
- const __m256i bit_6v_256 = _mm256_broadcast_i32x4(bit_6v);
154
-
155
- // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
156
- // 00 01 02 03
157
- const __m256i shuffle_mask = _mm256_setr_epi16(
158
- 0xFF00, 0x0100, 0x0201, 0xFF02,
159
- 0xFF03, 0x0403, 0x0504, 0xFF05,
160
- 0xFF06, 0x0706, 0x0807, 0xFF08,
161
- 0xFF09, 0x0A09, 0x0B0A, 0xFF0B);
162
- const __m256i shuffled = _mm256_shuffle_epi8(bit_6v_256, shuffle_mask);
163
-
164
- // 0: xxxxxxxx xx543210
165
- // 1: xxxx5432 10xxxxxx
166
- // 2: xxxxxx54 3210xxxx
167
- // 3: xxxxxxxx 543210xx
168
- const __m256i shift_right_v = _mm256_setr_epi16(
169
- 0x0U, 0x6U, 0x4U, 0x2U,
170
- 0x0U, 0x6U, 0x4U, 0x2U,
171
- 0x0U, 0x6U, 0x4U, 0x2U,
172
- 0x0U, 0x6U, 0x4U, 0x2U);
173
- __m256i shuffled_shifted = _mm256_srlv_epi16(shuffled, shift_right_v);
174
-
175
- // remove unneeded bits
176
- shuffled_shifted =
177
- _mm256_and_si256(shuffled_shifted, _mm256_set1_epi16(0x003F));
178
-
179
- // scale
180
- const __m512 f8 =
181
- _mm512_cvtepi32_ps(_mm512_cvtepi16_epi32(shuffled_shifted));
182
- const __m512 half_one_255 = _mm512_set1_ps(0.5f / 63.f);
183
- const __m512 one_255 = _mm512_set1_ps(1.f / 63.f);
184
- return simd16float32(_mm512_fmadd_ps(f8, one_255, half_one_255));
185
-
186
- // clang-format on
187
- }
188
- };
189
-
190
- /**********************************************************
191
- * Quantizers (uniform and non-uniform)
192
- **********************************************************/
193
-
194
- template <class Codec>
195
- struct QuantizerTemplate<
196
- Codec,
197
- scalar_quantizer::QuantizerTemplateScaling::UNIFORM,
198
- SIMDLevel::AVX512>
199
- : QuantizerTemplate<
200
- Codec,
201
- scalar_quantizer::QuantizerTemplateScaling::UNIFORM,
202
- SIMDLevel::NONE> {
203
- QuantizerTemplate(size_t d, const std::vector<float>& trained)
204
- : QuantizerTemplate<
205
- Codec,
206
- scalar_quantizer::QuantizerTemplateScaling::UNIFORM,
207
- SIMDLevel::NONE>(d, trained) {
208
- assert(d % 16 == 0);
209
- }
210
-
211
- FAISS_ALWAYS_INLINE simd16float32
212
- reconstruct_16_components(const uint8_t* code, int i) const {
213
- __m512 xi = Codec::decode_16_components(code, i).f;
214
- return simd16float32(_mm512_fmadd_ps(
215
- xi, _mm512_set1_ps(this->vdiff), _mm512_set1_ps(this->vmin)));
216
- }
217
-
218
- /// Raw codec decode without denormalization
219
- FAISS_ALWAYS_INLINE simd16float32
220
- decode_16_raw(const uint8_t* code, int i) const {
221
- return Codec::decode_16_components(code, i);
222
- }
223
- };
224
-
225
- template <class Codec>
226
- struct QuantizerTemplate<
227
- Codec,
228
- scalar_quantizer::QuantizerTemplateScaling::NON_UNIFORM,
229
- SIMDLevel::AVX512>
230
- : QuantizerTemplate<
231
- Codec,
232
- scalar_quantizer::QuantizerTemplateScaling::NON_UNIFORM,
233
- SIMDLevel::NONE> {
234
- QuantizerTemplate(size_t d, const std::vector<float>& trained)
235
- : QuantizerTemplate<
236
- Codec,
237
- scalar_quantizer::QuantizerTemplateScaling::NON_UNIFORM,
238
- SIMDLevel::NONE>(d, trained) {
239
- assert(d % 16 == 0);
240
- }
241
-
242
- FAISS_ALWAYS_INLINE simd16float32
243
- reconstruct_16_components(const uint8_t* code, int i) const {
244
- __m512 xi = Codec::decode_16_components(code, i).f;
245
- return simd16float32(_mm512_fmadd_ps(
246
- xi,
247
- _mm512_loadu_ps(this->vdiff + i),
248
- _mm512_loadu_ps(this->vmin + i)));
249
- }
250
- };
251
-
252
- /**********************************************************
253
- * Lloyd-Max scalar quantizer
254
- **********************************************************/
255
-
256
- // 1-bit Lloyd-Max AVX512: 16 comparisons → 2 bytes via mask compare.
257
- template <>
258
- struct QuantizerLloydMax<1, SIMDLevel::AVX512>
259
- : QuantizerLloydMax<1, SIMDLevel::NONE> {
260
- using Base = QuantizerLloydMax<1, SIMDLevel::NONE>;
261
-
262
- QuantizerLloydMax(size_t d, const std::vector<float>& trained)
263
- : Base(d, trained) {
264
- assert(d % 16 == 0);
265
- }
266
-
267
- FAISS_ALWAYS_INLINE simd16float32
268
- reconstruct_16_components(const uint8_t* code, int i) const {
269
- return simd16float32(_mm512_i32gather_ps(
270
- unpack_16x1bit_to_u32(code, i),
271
- this->centroids,
272
- sizeof(float)));
273
- }
274
-
275
- void encode_vector(const float* x, uint8_t* code) const final {
276
- __m512 boundary = _mm512_set1_ps(this->boundaries[0]);
277
- for (size_t i = 0; i < this->d; i += 16) {
278
- __m512 vals = _mm512_loadu_ps(x + i);
279
- __mmask16 mask = _mm512_cmp_ps_mask(vals, boundary, _CMP_GT_OQ);
280
- uint16_t bits = _cvtmask16_u32(mask);
281
- memcpy(code + i / 8, &bits, sizeof(uint16_t));
282
- }
283
- }
284
-
285
- void decode_vector(const uint8_t* code, float* x) const final {
286
- for (size_t i = 0; i < this->d; i += 16) {
287
- simd16float32 xi =
288
- reconstruct_16_components(code, static_cast<int>(i));
289
- _mm512_storeu_ps(x + i, xi.f);
290
- }
291
- }
292
- };
293
-
294
- // 2-4 bit Lloyd-Max AVX512: decode via gather, encode stays scalar.
295
- #define DEFINE_LLOYD_MAX_AVX512_MULTIBIT(NBITS, UNPACK_EXPR) \
296
- template <> \
297
- struct QuantizerLloydMax<NBITS, SIMDLevel::AVX512> \
298
- : QuantizerLloydMax<NBITS, SIMDLevel::NONE> { \
299
- using Base = QuantizerLloydMax<NBITS, SIMDLevel::NONE>; \
300
- \
301
- QuantizerLloydMax(size_t d, const std::vector<float>& trained) \
302
- : Base(d, trained) { \
303
- assert(d % 16 == 0); \
304
- } \
305
- \
306
- FAISS_ALWAYS_INLINE simd16float32 \
307
- reconstruct_16_components(const uint8_t* code, int i) const { \
308
- return simd16float32(_mm512_i32gather_ps( \
309
- (UNPACK_EXPR), this->centroids, sizeof(float))); \
310
- } \
311
- \
312
- void decode_vector(const uint8_t* code, float* x) const final { \
313
- for (size_t i = 0; i < this->d; i += 16) { \
314
- simd16float32 xi = \
315
- reconstruct_16_components(code, static_cast<int>(i)); \
316
- _mm512_storeu_ps(x + i, xi.f); \
317
- } \
318
- } \
319
- }
320
-
321
- DEFINE_LLOYD_MAX_AVX512_MULTIBIT(2, unpack_16x2bit_to_u32(code, i));
322
- DEFINE_LLOYD_MAX_AVX512_MULTIBIT(3, unpack_16x3bit_to_u32(code, i));
323
- DEFINE_LLOYD_MAX_AVX512_MULTIBIT(4, unpack_16x4bit_to_u32(code, i));
324
-
325
- #undef DEFINE_LLOYD_MAX_AVX512_MULTIBIT
326
-
327
- // 8-bit Lloyd-Max AVX512
328
- template <>
329
- struct QuantizerLloydMax<8, SIMDLevel::AVX512>
330
- : QuantizerLloydMax<8, SIMDLevel::NONE> {
331
- using Base = QuantizerLloydMax<8, SIMDLevel::NONE>;
332
-
333
- QuantizerLloydMax(size_t d, const std::vector<float>& trained)
334
- : Base(d, trained) {
335
- assert(d % 16 == 0);
336
- }
337
-
338
- FAISS_ALWAYS_INLINE simd16float32
339
- reconstruct_16_components(const uint8_t* code, int i) const {
340
- const __m128i packed = _mm_loadu_si128(
341
- (const __m128i*)(code + static_cast<size_t>(i)));
342
- const __m512i indices = _mm512_cvtepu8_epi32(packed);
343
- return simd16float32(
344
- _mm512_i32gather_ps(indices, this->centroids, sizeof(float)));
345
- }
346
-
347
- void decode_vector(const uint8_t* code, float* x) const final {
348
- for (size_t i = 0; i < this->d; i += 16) {
349
- simd16float32 xi =
350
- reconstruct_16_components(code, static_cast<int>(i));
351
- _mm512_storeu_ps(x + i, xi.f);
352
- }
353
- }
354
- };
355
-
356
- /**********************************************************
357
- * FP16 Quantizer
358
- **********************************************************/
359
-
360
- template <>
361
- struct QuantizerFP16<SIMDLevel::AVX512> : QuantizerFP16<SIMDLevel::NONE> {
362
- QuantizerFP16(size_t d, const std::vector<float>& trained)
363
- : QuantizerFP16<SIMDLevel::NONE>(d, trained) {
364
- assert(d % 16 == 0);
365
- }
366
-
367
- FAISS_ALWAYS_INLINE simd16float32
368
- reconstruct_16_components(const uint8_t* code, int i) const {
369
- __m256i codei = _mm256_loadu_si256((const __m256i*)(code + 2 * i));
370
- return simd16float32(_mm512_cvtph_ps(codei));
371
- }
372
- };
373
-
374
- /**********************************************************
375
- * BF16 Quantizer
376
- **********************************************************/
377
-
378
- template <>
379
- struct QuantizerBF16<SIMDLevel::AVX512> : QuantizerBF16<SIMDLevel::NONE> {
380
- QuantizerBF16(size_t d, const std::vector<float>& trained)
381
- : QuantizerBF16<SIMDLevel::NONE>(d, trained) {
382
- assert(d % 16 == 0);
383
- }
384
-
385
- FAISS_ALWAYS_INLINE simd16float32
386
- reconstruct_16_components(const uint8_t* code, int i) const {
387
- __m256i code_256i = _mm256_loadu_si256((const __m256i*)(code + 2 * i));
388
- __m512i code_512i = _mm512_cvtepu16_epi32(code_256i);
389
- code_512i = _mm512_slli_epi32(code_512i, 16);
390
- return simd16float32(_mm512_castsi512_ps(code_512i));
391
- }
392
- };
393
-
394
- /**********************************************************
395
- * 8bit Direct Quantizer
396
- **********************************************************/
397
-
398
- template <>
399
- struct Quantizer8bitDirect<SIMDLevel::AVX512>
400
- : Quantizer8bitDirect<SIMDLevel::NONE> {
401
- Quantizer8bitDirect(size_t d, const std::vector<float>& trained)
402
- : Quantizer8bitDirect<SIMDLevel::NONE>(d, trained) {
403
- assert(d % 16 == 0);
404
- }
405
-
406
- FAISS_ALWAYS_INLINE simd16float32
407
- reconstruct_16_components(const uint8_t* code, int i) const {
408
- __m128i x16 = _mm_loadu_si128((__m128i*)(code + i)); // 16 * int8
409
- __m512i y16 = _mm512_cvtepu8_epi32(x16); // 16 * int32
410
- return simd16float32(_mm512_cvtepi32_ps(y16)); // 16 * float32
411
- }
412
- };
413
-
414
- /**********************************************************
415
- * 8bit Direct Signed Quantizer
416
- **********************************************************/
417
-
418
- template <>
419
- struct Quantizer8bitDirectSigned<SIMDLevel::AVX512>
420
- : Quantizer8bitDirectSigned<SIMDLevel::NONE> {
421
- Quantizer8bitDirectSigned(size_t d, const std::vector<float>& trained)
422
- : Quantizer8bitDirectSigned<SIMDLevel::NONE>(d, trained) {
423
- assert(d % 16 == 0);
424
- }
425
-
426
- FAISS_ALWAYS_INLINE simd16float32
427
- reconstruct_16_components(const uint8_t* code, int i) const {
428
- __m128i x16 = _mm_loadu_si128((__m128i*)(code + i)); // 16 * int8
429
- __m512i y16 = _mm512_cvtepu8_epi32(x16); // 16 * int32
430
- __m512i c16 = _mm512_set1_epi32(128);
431
- __m512i z16 = _mm512_sub_epi32(y16, c16); // subtract 128 from all lanes
432
- return simd16float32(_mm512_cvtepi32_ps(z16)); // 16 * float32
433
- }
434
- };
435
-
436
- /**********************************************************
437
- * Similarities (L2 and IP)
438
- **********************************************************/
439
-
440
- template <>
441
- struct SimilarityL2<SIMDLevel::AVX512> {
442
- static constexpr int simdwidth = 16;
443
- static constexpr SIMDLevel simd_level = SIMDLevel::AVX512;
444
- static constexpr MetricType metric_type = METRIC_L2;
445
-
446
- const float *y, *yi;
447
-
448
- explicit SimilarityL2(const float* y) : y(y), yi(nullptr) {}
449
-
450
- simd16float32 accu16;
451
-
452
- FAISS_ALWAYS_INLINE void begin_16() {
453
- accu16.clear();
454
- yi = y;
455
- }
456
-
457
- FAISS_ALWAYS_INLINE void add_16_components(simd16float32 x) {
458
- simd16float32 yiv(yi);
459
- yi += 16;
460
- simd16float32 tmp = yiv - x;
461
- accu16 = accu16 + tmp * tmp;
462
- }
463
-
464
- FAISS_ALWAYS_INLINE void add_16_components_2(
465
- simd16float32 x,
466
- simd16float32 y_2) {
467
- simd16float32 tmp = y_2 - x;
468
- accu16 = accu16 + tmp * tmp;
469
- }
470
-
471
- FAISS_ALWAYS_INLINE float result_16() {
472
- return horizontal_add(accu16);
473
- }
474
-
475
- static void adjust_query_for_raw_decode(
476
- const float* x,
477
- float* q_adj,
478
- size_t d,
479
- float vmin,
480
- float vdiff,
481
- float& scale_factor,
482
- float& bias) {
483
- float inv_vdiff = (vdiff != 0) ? 1.0f / vdiff : 0.0f;
484
- for (size_t i = 0; i < d; i++) {
485
- q_adj[i] = (x[i] - vmin) * inv_vdiff;
486
- }
487
- scale_factor = vdiff * vdiff;
488
- bias = 0;
489
- }
490
- };
491
-
492
- template <>
493
- struct SimilarityIP<SIMDLevel::AVX512> {
494
- static constexpr int simdwidth = 16;
495
- static constexpr SIMDLevel simd_level = SIMDLevel::AVX512;
496
- static constexpr MetricType metric_type = METRIC_INNER_PRODUCT;
497
-
498
- const float *y, *yi;
499
-
500
- explicit SimilarityIP(const float* y) : y(y), yi(nullptr) {}
501
-
502
- simd16float32 accu16;
503
-
504
- FAISS_ALWAYS_INLINE void begin_16() {
505
- accu16.clear();
506
- yi = y;
507
- }
508
-
509
- FAISS_ALWAYS_INLINE void add_16_components(simd16float32 x) {
510
- simd16float32 yiv(yi);
511
- yi += 16;
512
- accu16 = accu16 + yiv * x;
513
- }
514
-
515
- FAISS_ALWAYS_INLINE void add_16_components_2(
516
- simd16float32 x1,
517
- simd16float32 x2) {
518
- accu16 = accu16 + x1 * x2;
519
- }
520
-
521
- FAISS_ALWAYS_INLINE float result_16() {
522
- return horizontal_add(accu16);
523
- }
524
-
525
- static void adjust_query_for_raw_decode(
526
- const float* x,
527
- float* q_adj,
528
- size_t d,
529
- float vmin,
530
- float vdiff,
531
- float& scale_factor,
532
- float& bias) {
533
- float sum_q = 0;
534
- for (size_t i = 0; i < d; i++) {
535
- q_adj[i] = x[i];
536
- sum_q += x[i];
537
- }
538
- scale_factor = vdiff;
539
- bias = vmin * sum_q;
540
- }
541
- };
542
-
543
- /**********************************************************
544
- * Distance Computers
545
- **********************************************************/
546
-
547
- template <class Quantizer, class Similarity>
548
- struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX512>
549
- : SQDistanceComputer {
550
- using Sim = Similarity;
551
-
552
- Quantizer quant;
553
-
554
- // Pre-adjusted query buffer for uniform quantizers
555
- std::vector<float> q_adj;
556
- float scale_factor = 0;
557
- float bias = 0;
558
-
559
- static constexpr bool has_decode_raw() {
560
- return requires(const Quantizer& q, const uint8_t* c, int i) {
561
- { q.decode_16_raw(c, i) };
562
- };
563
- }
564
-
565
- DCTemplate(size_t d, const std::vector<float>& trained)
566
- : quant(d, trained) {
567
- if constexpr (has_decode_raw()) {
568
- q_adj.resize(d);
569
- }
570
- }
571
-
572
- float compute_distance(const float* x, const uint8_t* code) const {
573
- Similarity sim(x);
574
- sim.begin_16();
575
- for (size_t i = 0; i < quant.d; i += 16) {
576
- simd16float32 xi = quant.reconstruct_16_components(code, i);
577
- sim.add_16_components(xi);
578
- }
579
- return sim.result_16();
580
- }
581
-
582
- float compute_code_distance(const uint8_t* code1, const uint8_t* code2)
583
- const {
584
- Similarity sim(nullptr);
585
- sim.begin_16();
586
- for (size_t i = 0; i < quant.d; i += 16) {
587
- simd16float32 x1 = quant.reconstruct_16_components(code1, i);
588
- simd16float32 x2 = quant.reconstruct_16_components(code2, i);
589
- sim.add_16_components_2(x1, x2);
590
- }
591
- return sim.result_16();
592
- }
593
-
594
- void set_query(const float* x) final {
595
- q = x;
596
- if constexpr (has_decode_raw()) {
597
- Sim::adjust_query_for_raw_decode(
598
- x,
599
- q_adj.data(),
600
- quant.d,
601
- quant.vmin,
602
- quant.vdiff,
603
- scale_factor,
604
- bias);
605
- }
606
- }
607
-
608
- float query_to_code_predecoded(const uint8_t* code) const {
609
- Similarity sim(q_adj.data());
610
- sim.begin_16();
611
- for (size_t i = 0; i < quant.d; i += 16) {
612
- simd16float32 xi = quant.decode_16_raw(code, i);
613
- sim.add_16_components(xi);
614
- }
615
- return bias + scale_factor * sim.result_16();
616
- }
617
-
618
- float symmetric_dis(idx_t i, idx_t j) override {
619
- return compute_code_distance(
620
- codes + i * code_size, codes + j * code_size);
621
- }
622
-
623
- float query_to_code(const uint8_t* code) const final {
624
- if constexpr (has_decode_raw()) {
625
- return query_to_code_predecoded(code);
626
- } else {
627
- return compute_distance(q, code);
628
- }
629
- }
630
-
631
- void query_to_codes_batch_4(
632
- const uint8_t* code_0,
633
- const uint8_t* code_1,
634
- const uint8_t* code_2,
635
- const uint8_t* code_3,
636
- float& dis0,
637
- float& dis1,
638
- float& dis2,
639
- float& dis3) const final {
640
- Similarity sim0(q);
641
- Similarity sim1(q);
642
- Similarity sim2(q);
643
- Similarity sim3(q);
644
-
645
- sim0.begin_16();
646
- sim1.begin_16();
647
- sim2.begin_16();
648
- sim3.begin_16();
649
-
650
- for (size_t i = 0; i < quant.d; i += 16) {
651
- simd16float32 xi0 = quant.reconstruct_16_components(code_0, i);
652
- simd16float32 xi1 = quant.reconstruct_16_components(code_1, i);
653
- simd16float32 xi2 = quant.reconstruct_16_components(code_2, i);
654
- simd16float32 xi3 = quant.reconstruct_16_components(code_3, i);
655
- sim0.add_16_components(xi0);
656
- sim1.add_16_components(xi1);
657
- sim2.add_16_components(xi2);
658
- sim3.add_16_components(xi3);
659
- }
660
-
661
- dis0 = sim0.result_16();
662
- dis1 = sim1.result_16();
663
- dis2 = sim2.result_16();
664
- dis3 = sim3.result_16();
665
- }
666
- };
667
-
668
16
  template <class Similarity>
669
17
  struct DistanceComputerByte<Similarity, SIMDLevel::AVX512>
670
18
  : SQDistanceComputer {
@@ -787,50 +135,7 @@ struct DistanceComputerByteSigned<Similarity, SIMDLevel::AVX512>
787
135
  }
788
136
  };
789
137
 
790
- /**********************************************************
791
- * TurboQuant masked_sum AVX512 specialization
792
- **********************************************************/
793
-
794
- template <SIMDLevel SL0>
795
- float turboq_masked_sum(const float* arr, const uint8_t* bits, size_t d);
796
-
797
- template <>
798
- float turboq_masked_sum<SIMDLevel::AVX512>(
799
- const float* arr,
800
- const uint8_t* bits,
801
- size_t d) {
802
- __m512 acc = _mm512_setzero_ps();
803
- size_t i = 0;
804
- size_t full_16 = (d / 16) * 16;
805
- for (; i < full_16; i += 16) {
806
- uint16_t mask16;
807
- memcpy(&mask16, bits + i / 8, sizeof(mask16));
808
- __mmask16 k = _cvtu32_mask16(mask16);
809
- __m512 vals = _mm512_loadu_ps(arr + i);
810
- acc = _mm512_mask_add_ps(acc, k, acc, vals);
811
- }
812
- float result = _mm512_reduce_add_ps(acc);
813
- if (i < d) {
814
- size_t remaining = d - i;
815
- __mmask16 tail_mask = _cvtu32_mask16((1u << remaining) - 1);
816
- __m512 tail_vals = _mm512_maskz_loadu_ps(tail_mask, arr + i);
817
- uint16_t bits_tail = 0;
818
- size_t bytes_remaining = (remaining + 7) / 8;
819
- memcpy(&bits_tail, bits + i / 8, bytes_remaining);
820
- __mmask16 bits_k = _cvtu32_mask16(bits_tail);
821
- __mmask16 combined = _kand_mask16(tail_mask, bits_k);
822
- __m512 masked_tail = _mm512_maskz_mov_ps(combined, tail_vals);
823
- result += _mm512_reduce_add_ps(masked_tail);
824
- }
825
- return result;
826
- }
827
-
828
138
  } // namespace scalar_quantizer
829
139
  } // namespace faiss
830
140
 
831
- #ifndef SQ_AVX512_SKIP_DISPATCH
832
- #define THE_LEVEL_TO_DISPATCH SIMDLevel::AVX512
833
141
  #include <faiss/impl/scalar_quantizer/sq-dispatch.h>
834
- #endif
835
-
836
- #endif // COMPILE_SIMD_AVX512