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
@@ -7,11 +7,93 @@
7
7
 
8
8
  #pragma once
9
9
 
10
+ #include <algorithm>
11
+ #include <cstddef>
12
+ #include <cstdint>
13
+ #include <memory>
14
+
10
15
  #include <faiss/impl/ResultHandler.h>
16
+ #include <faiss/utils/distances.h>
11
17
  #include <faiss/utils/simd_levels.h>
18
+ #include <faiss/utils/utils.h>
12
19
 
13
20
  namespace faiss {
14
21
 
22
+ /** fp32 query tiles for the BLAS exhaustive-search kernels.
23
+ *
24
+ * A kernel calls prepare_norms() once, then tile(i0, i1, x_norms) for each
25
+ * query tile; the returned rows stay valid until the next tile() call.
26
+ */
27
+ struct Fp32QueryTiles {
28
+ const float* x;
29
+ size_t d;
30
+
31
+ /// squared L2 norms of all nx queries
32
+ void prepare_norms(size_t nx, float* x_norms) const {
33
+ fvec_norms_L2sqr(x_norms, x, d, nx);
34
+ }
35
+
36
+ const float* tile(size_t i0, size_t /*i1*/, float* /*x_norms*/) const {
37
+ return x + i0 * d;
38
+ }
39
+ };
40
+
41
+ /** Packed IEEE binary16 query tiles for the BLAS exhaustive-search kernels.
42
+ *
43
+ * Queries are widened in chunks of whole tiles (at most chunk_bytes of fp32,
44
+ * at least one tile) into a buffer reused across chunks: the fp32 copy stays
45
+ * bounded and each widened tile serves all database tiles. Norms are computed
46
+ * from the widened rows, so results match the fp32 kernels on the widened
47
+ * queries.
48
+ */
49
+ struct Fp16QueryTiles {
50
+ static constexpr size_t chunk_bytes = size_t(16) << 20;
51
+
52
+ const uint16_t* x;
53
+ size_t d;
54
+ size_t nx;
55
+ std::unique_ptr<float[]> buffer;
56
+ size_t chunk_rows = 0;
57
+ size_t chunk_begin = 0;
58
+ size_t chunk_end = 0;
59
+
60
+ Fp16QueryTiles(const uint16_t* x_in, size_t d_in, size_t nx_in)
61
+ : x(x_in), d(d_in), nx(nx_in) {}
62
+
63
+ void prepare_norms(size_t /*nx*/, float* /*x_norms*/) const {}
64
+
65
+ /** widened rows [i0, i1), and their norms if x_norms is not null
66
+ *
67
+ * Tiles are requested in order, all of the same size except the last.
68
+ */
69
+ const float* tile(size_t i0, size_t i1, float* x_norms) {
70
+ if (i1 > chunk_end) {
71
+ if (!buffer) {
72
+ const size_t tile_rows = i1 - i0;
73
+ chunk_rows =
74
+ tile_rows *
75
+ std::max<size_t>(
76
+ 1,
77
+ chunk_bytes / (tile_rows * d * sizeof(float)));
78
+ chunk_rows = std::min(chunk_rows, nx - i0);
79
+ buffer.reset(new float[chunk_rows * d]);
80
+ }
81
+ chunk_begin = i0;
82
+ chunk_end = std::min(nx, i0 + chunk_rows);
83
+ const int64_t n = static_cast<int64_t>(chunk_end - chunk_begin);
84
+ #pragma omp parallel for if (n * static_cast<int64_t>(d) > (1 << 16))
85
+ for (int64_t i = 0; i < n; i++) {
86
+ float* row = buffer.get() + i * d;
87
+ fp16_to_fp32(d, x + (chunk_begin + i) * d, row);
88
+ if (x_norms) {
89
+ x_norms[chunk_begin + i] = fvec_norm_L2sqr(row, d);
90
+ }
91
+ }
92
+ }
93
+ return buffer.get() + (i0 - chunk_begin) * d;
94
+ }
95
+ };
96
+
15
97
  /// BLAS-accelerated exhaustive L2 search for the k=1 (top-1) case.
16
98
  /// Specializations live in the per-SIMD translation units under simd_impl/.
17
99
  template <SIMDLevel>
@@ -24,4 +106,15 @@ void exhaustive_L2sqr_blas_cmax(
24
106
  Top1BlockResultHandler<CMax<float, int64_t>>& res,
25
107
  const float* y_norms);
26
108
 
109
+ /// Same as exhaustive_L2sqr_blas_cmax for packed IEEE binary16 queries.
110
+ template <SIMDLevel>
111
+ void exhaustive_L2sqr_blas_cmax_fp16(
112
+ const uint16_t* x,
113
+ const float* y,
114
+ size_t d,
115
+ size_t nx,
116
+ size_t ny,
117
+ Top1BlockResultHandler<CMax<float, int64_t>>& res,
118
+ const float* y_norms);
119
+
27
120
  } // namespace faiss
@@ -0,0 +1,76 @@
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 <cstddef>
11
+ #include <cstdint>
12
+
13
+ #include <faiss/utils/fp16.h>
14
+ #include <faiss/utils/simd_levels.h>
15
+
16
+ namespace faiss {
17
+ namespace detail {
18
+
19
+ // c[j] += fp32(x[j]) * w for j < d
20
+ template <SIMDLevel Level>
21
+ inline void fp16_madd(size_t d, const uint16_t* x, float w, float* c) {
22
+ for (size_t j = 0; j < d; ++j) {
23
+ c[j] += decode_fp16(x[j]) * w;
24
+ }
25
+ }
26
+
27
+ template <SIMDLevel Level>
28
+ inline void fp16_to_fp32_kernel(size_t n, const uint16_t* x, float* out) {
29
+ for (size_t j = 0; j < n; ++j) {
30
+ out[j] = decode_fp16(x[j]);
31
+ }
32
+ }
33
+
34
+ #ifdef COMPILE_SIMD_AVX2
35
+ template <>
36
+ void fp16_madd<SIMDLevel::AVX2>(size_t d, const uint16_t* x, float w, float* c);
37
+
38
+ template <>
39
+ void fp16_to_fp32_kernel<SIMDLevel::AVX2>(
40
+ size_t n,
41
+ const uint16_t* x,
42
+ float* out);
43
+ #endif
44
+
45
+ #ifdef COMPILE_SIMD_AVX512
46
+ template <>
47
+ void fp16_madd<SIMDLevel::AVX512>(
48
+ size_t d,
49
+ const uint16_t* x,
50
+ float w,
51
+ float* c);
52
+
53
+ template <>
54
+ void fp16_to_fp32_kernel<SIMDLevel::AVX512>(
55
+ size_t n,
56
+ const uint16_t* x,
57
+ float* out);
58
+ #endif
59
+
60
+ #ifdef COMPILE_SIMD_ARM_NEON
61
+ template <>
62
+ void fp16_madd<SIMDLevel::ARM_NEON>(
63
+ size_t d,
64
+ const uint16_t* x,
65
+ float w,
66
+ float* c);
67
+
68
+ template <>
69
+ void fp16_to_fp32_kernel<SIMDLevel::ARM_NEON>(
70
+ size_t n,
71
+ const uint16_t* x,
72
+ float* out);
73
+ #endif
74
+
75
+ } // namespace detail
76
+ } // namespace faiss
@@ -0,0 +1,52 @@
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/utils/simd_impl/fp16_kernels.h>
9
+
10
+ #include <immintrin.h>
11
+
12
+ namespace faiss {
13
+ namespace detail {
14
+
15
+ template <>
16
+ void fp16_madd<SIMDLevel::AVX2>(
17
+ size_t d,
18
+ const uint16_t* x,
19
+ float w,
20
+ float* c) {
21
+ const __m256 wv = _mm256_set1_ps(w);
22
+ size_t j = 0;
23
+ for (; j + 8 <= d; j += 8) {
24
+ const __m256 xv = _mm256_cvtph_ps(
25
+ _mm_loadu_si128(reinterpret_cast<const __m128i*>(x + j)));
26
+ _mm256_storeu_ps(
27
+ c + j,
28
+ _mm256_add_ps(_mm256_loadu_ps(c + j), _mm256_mul_ps(xv, wv)));
29
+ }
30
+ for (; j < d; ++j) {
31
+ c[j] += decode_fp16(x[j]) * w;
32
+ }
33
+ }
34
+
35
+ template <>
36
+ void fp16_to_fp32_kernel<SIMDLevel::AVX2>(
37
+ size_t n,
38
+ const uint16_t* x,
39
+ float* out) {
40
+ size_t j = 0;
41
+ for (; j + 8 <= n; j += 8) {
42
+ const __m128i h =
43
+ _mm_loadu_si128(reinterpret_cast<const __m128i*>(x + j));
44
+ _mm256_storeu_ps(out + j, _mm256_cvtph_ps(h));
45
+ }
46
+ for (; j < n; ++j) {
47
+ out[j] = decode_fp16(x[j]);
48
+ }
49
+ }
50
+
51
+ } // namespace detail
52
+ } // namespace faiss
@@ -0,0 +1,52 @@
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/utils/simd_impl/fp16_kernels.h>
9
+
10
+ #include <immintrin.h>
11
+
12
+ namespace faiss {
13
+ namespace detail {
14
+
15
+ template <>
16
+ void fp16_madd<SIMDLevel::AVX512>(
17
+ size_t d,
18
+ const uint16_t* x,
19
+ float w,
20
+ float* c) {
21
+ const __m512 wv = _mm512_set1_ps(w);
22
+ size_t j = 0;
23
+ for (; j + 16 <= d; j += 16) {
24
+ const __m512 xv = _mm512_cvtph_ps(
25
+ _mm256_loadu_si256(reinterpret_cast<const __m256i*>(x + j)));
26
+ _mm512_storeu_ps(
27
+ c + j,
28
+ _mm512_add_ps(_mm512_loadu_ps(c + j), _mm512_mul_ps(xv, wv)));
29
+ }
30
+ for (; j < d; ++j) {
31
+ c[j] += decode_fp16(x[j]) * w;
32
+ }
33
+ }
34
+
35
+ template <>
36
+ void fp16_to_fp32_kernel<SIMDLevel::AVX512>(
37
+ size_t n,
38
+ const uint16_t* x,
39
+ float* out) {
40
+ size_t j = 0;
41
+ for (; j + 16 <= n; j += 16) {
42
+ const __m256i h =
43
+ _mm256_loadu_si256(reinterpret_cast<const __m256i*>(x + j));
44
+ _mm512_storeu_ps(out + j, _mm512_cvtph_ps(h));
45
+ }
46
+ for (; j < n; ++j) {
47
+ out[j] = decode_fp16(x[j]);
48
+ }
49
+ }
50
+
51
+ } // namespace detail
52
+ } // namespace faiss
@@ -0,0 +1,48 @@
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/utils/simd_impl/fp16_kernels.h>
9
+
10
+ #include <arm_neon.h>
11
+
12
+ namespace faiss {
13
+ namespace detail {
14
+
15
+ template <>
16
+ void fp16_madd<SIMDLevel::ARM_NEON>(
17
+ size_t d,
18
+ const uint16_t* x,
19
+ float w,
20
+ float* c) {
21
+ const float32x4_t wv = vdupq_n_f32(w);
22
+ size_t j = 0;
23
+ for (; j + 4 <= d; j += 4) {
24
+ const float32x4_t xv =
25
+ vcvt_f32_f16(vreinterpret_f16_u16(vld1_u16(x + j)));
26
+ vst1q_f32(c + j, vaddq_f32(vld1q_f32(c + j), vmulq_f32(xv, wv)));
27
+ }
28
+ for (; j < d; ++j) {
29
+ c[j] += decode_fp16(x[j]) * w;
30
+ }
31
+ }
32
+
33
+ template <>
34
+ void fp16_to_fp32_kernel<SIMDLevel::ARM_NEON>(
35
+ size_t n,
36
+ const uint16_t* x,
37
+ float* out) {
38
+ size_t j = 0;
39
+ for (; j + 4 <= n; j += 4) {
40
+ vst1q_f32(out + j, vcvt_f32_f16(vreinterpret_f16_u16(vld1_u16(x + j))));
41
+ }
42
+ for (; j < n; ++j) {
43
+ out[j] = decode_fp16(x[j]);
44
+ }
45
+ }
46
+
47
+ } // namespace detail
48
+ } // namespace faiss
@@ -0,0 +1,44 @@
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 <immintrin.h>
11
+
12
+ #include <faiss/utils/simd_impl/masked_sum.h>
13
+
14
+ namespace faiss {
15
+ namespace {
16
+
17
+ template <>
18
+ inline float masked_sum<SIMDLevel::AVX2>(
19
+ const float* x,
20
+ const uint8_t* bits,
21
+ size_t d) {
22
+ const __m256i bit_masks = _mm256_set_epi32(128, 64, 32, 16, 8, 4, 2, 1);
23
+ __m256 acc = _mm256_setzero_ps();
24
+ const size_t full_bytes = d / 8;
25
+ for (size_t byte_idx = 0; byte_idx < full_bytes; byte_idx++) {
26
+ const __m256i byte_broadcast = _mm256_set1_epi32(bits[byte_idx]);
27
+ const __m256i masked = _mm256_and_si256(byte_broadcast, bit_masks);
28
+ const __m256 mask =
29
+ _mm256_castsi256_ps(_mm256_cmpeq_epi32(masked, bit_masks));
30
+ const __m256 vals = _mm256_loadu_ps(x + byte_idx * 8);
31
+ acc = _mm256_add_ps(acc, _mm256_and_ps(mask, vals));
32
+ }
33
+ __m128 sum128 = _mm_add_ps(
34
+ _mm256_castps256_ps128(acc), _mm256_extractf128_ps(acc, 1));
35
+ __m128 shuf = _mm_movehdup_ps(sum128);
36
+ __m128 sums = _mm_add_ps(sum128, shuf);
37
+ shuf = _mm_movehl_ps(shuf, sums);
38
+ sums = _mm_add_ss(sums, shuf);
39
+ return _mm_cvtss_f32(sums) +
40
+ masked_sum_scalar(x + full_bytes * 8, bits + full_bytes, d % 8);
41
+ }
42
+
43
+ } // namespace
44
+ } // namespace faiss
@@ -0,0 +1,43 @@
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 <cstring>
11
+
12
+ #include <immintrin.h>
13
+
14
+ #include <faiss/utils/simd_impl/masked_sum.h>
15
+
16
+ namespace faiss {
17
+ namespace {
18
+
19
+ template <>
20
+ inline float masked_sum<SIMDLevel::AVX512>(
21
+ const float* x,
22
+ const uint8_t* bits,
23
+ size_t d) {
24
+ __m512 acc = _mm512_setzero_ps();
25
+ size_t i = 0;
26
+ for (; i + 16 <= d; i += 16) {
27
+ uint16_t mask16;
28
+ memcpy(&mask16, bits + i / 8, sizeof(mask16));
29
+ acc = _mm512_mask_add_ps(acc, mask16, acc, _mm512_loadu_ps(x + i));
30
+ }
31
+ if (i < d) {
32
+ uint32_t mask = bits[i / 8];
33
+ if (d - i > 8) {
34
+ mask |= uint32_t(bits[i / 8 + 1]) << 8;
35
+ }
36
+ const __mmask16 k = mask & ((1u << (d - i)) - 1);
37
+ acc = _mm512_add_ps(acc, _mm512_maskz_loadu_ps(k, x + i));
38
+ }
39
+ return _mm512_reduce_add_ps(acc);
40
+ }
41
+
42
+ } // namespace
43
+ } // namespace faiss
@@ -0,0 +1,38 @@
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 <cstddef>
11
+ #include <cstdint>
12
+
13
+ #include <faiss/utils/simd_levels.h>
14
+
15
+ namespace faiss {
16
+
17
+ // Internal linkage: each file compiles these with its own flags.
18
+ // masked_sum-avx2.h and masked_sum-avx512.h specialize masked_sum.
19
+ namespace {
20
+
21
+ inline float masked_sum_scalar(const float* x, const uint8_t* bits, size_t d) {
22
+ float sum = 0;
23
+ for (size_t j = 0; j < d; j++) {
24
+ if ((bits[j / 8] >> (j % 8)) & 1) {
25
+ sum += x[j];
26
+ }
27
+ }
28
+ return sum;
29
+ }
30
+
31
+ template <SIMDLevel SL>
32
+ inline float masked_sum(const float* x, const uint8_t* bits, size_t d) {
33
+ return masked_sum_scalar(x, bits, d);
34
+ }
35
+
36
+ } // namespace
37
+
38
+ } // namespace faiss
@@ -5,10 +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
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
12
10
  #include <faiss/utils/simd_impl/partitioning_simdlib256.h>
13
-
14
- #endif // COMPILE_SIMD_AVX2
@@ -5,10 +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
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
12
10
  #include <faiss/utils/simd_impl/partitioning_simdlib256.h>
13
-
14
- #endif // COMPILE_SIMD_ARM_NEON
@@ -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/rabitq_simd.h>
11
9
  #include <immintrin.h>
12
10
  #include <limits>
@@ -275,9 +273,11 @@ uint64_t bitwise_and_dot_product<SIMDLevel::AVX2>(
275
273
  }
276
274
  sum += reduce_add_128(sum_128);
277
275
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
278
- const uint64_t yv = *(const uint64_t*)(data + offset);
276
+ uint64_t yv;
277
+ std::memcpy(&yv, data + offset, sizeof(yv));
279
278
  for (int j = 0; j < qb; j++) {
280
- const uint64_t qv = *(const uint64_t*)(query + j * size + offset);
279
+ uint64_t qv;
280
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
281
281
  sum += popcount64(qv & yv) << j;
282
282
  }
283
283
  }
@@ -336,10 +336,12 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
336
336
  dot_product += reduce_add_128(dot_128);
337
337
  popcount_sum += reduce_add_128(pop_128);
338
338
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
339
- const uint64_t yv = *(const uint64_t*)(data + offset);
339
+ uint64_t yv;
340
+ std::memcpy(&yv, data + offset, sizeof(yv));
340
341
  popcount_sum += popcount64(yv);
341
342
  for (int j = 0; j < qb; j++) {
342
- const uint64_t qv = *(const uint64_t*)(query + j * size + offset);
343
+ uint64_t qv;
344
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
343
345
  dot_product += popcount64(qv & yv) << j;
344
346
  }
345
347
  }
@@ -391,9 +393,11 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::AVX2>(
391
393
  }
392
394
  sum += reduce_add_128(sum_128);
393
395
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
394
- const auto yv = *(const uint64_t*)(data + offset);
396
+ uint64_t yv;
397
+ std::memcpy(&yv, data + offset, sizeof(yv));
395
398
  for (int j = 0; j < qb; j++) {
396
- const auto qv = *(const uint64_t*)(query + j * size + offset);
399
+ uint64_t qv;
400
+ std::memcpy(&qv, query + j * size + offset, sizeof(qv));
397
401
  sum += popcount64(qv ^ yv) << j;
398
402
  }
399
403
  }
@@ -427,7 +431,8 @@ uint64_t popcount<SIMDLevel::AVX2>(const uint8_t* data, size_t size) {
427
431
  }
428
432
  sum += reduce_add_128(sum_128);
429
433
  for (size_t step = 64 / 8; offset + step <= size; offset += step) {
430
- const auto yv = *(const uint64_t*)(data + offset);
434
+ uint64_t yv;
435
+ std::memcpy(&yv, data + offset, sizeof(yv));
431
436
  sum += popcount64(yv);
432
437
  }
433
438
  for (; offset < size; ++offset) {
@@ -517,7 +522,6 @@ inline float ip_1exbit_avx2(
517
522
  return result;
518
523
  }
519
524
 
520
- #ifdef __BMI2__
521
525
  inline float ip_bitplane_avx2(
522
526
  const uint8_t* __restrict sign_bits,
523
527
  const uint8_t* __restrict ex_code,
@@ -571,7 +575,6 @@ inline float ip_bitplane_avx2(
571
575
  result += ip_scalar(sign_bits, ex_code, rotated_q, i, d, ex_bits, cb);
572
576
  return result;
573
577
  }
574
- #endif // __BMI2__
575
578
 
576
579
  } // namespace
577
580
 
@@ -583,18 +586,54 @@ float compute_inner_product<SIMDLevel::AVX2>(
583
586
  size_t d,
584
587
  size_t ex_bits,
585
588
  float cb) {
589
+ if (ex_bits == 8) {
590
+ // Eight byte-aligned extra codes, plus their independent sign bits.
591
+ // One sign-word broadcast serves 32 dims, to save shuffle-port uops.
592
+ __m256 acc0 = _mm256_setzero_ps();
593
+ __m256 acc1 = _mm256_setzero_ps();
594
+ const __m256 weight = _mm256_set1_ps(256.f);
595
+ const __m256 offset = _mm256_set1_ps(cb);
596
+ const __m256i positions =
597
+ _mm256_setr_epi32(1, 2, 4, 8, 16, 32, 64, 128);
598
+ // cmpeq, not cmpgt: bit 31 of the shifted positions is a sign bit.
599
+ auto step = [&](__m256& acc, size_t i, __m256i signs, __m256i pos) {
600
+ const __m128i bytes = _mm_loadl_epi64(
601
+ reinterpret_cast<const __m128i*>(ex_code + i));
602
+ const __m256 extra =
603
+ _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(bytes));
604
+ const __m256i mask =
605
+ _mm256_cmpeq_epi32(_mm256_and_si256(signs, pos), pos);
606
+ const __m256 recon = _mm256_add_ps(
607
+ extra, _mm256_and_ps(_mm256_castsi256_ps(mask), weight));
608
+ acc = _mm256_fmadd_ps(
609
+ _mm256_loadu_ps(rotated_q + i),
610
+ _mm256_add_ps(recon, offset),
611
+ acc);
612
+ };
613
+ size_t i = 0;
614
+ for (; i + 32 <= d; i += 32) {
615
+ uint32_t word;
616
+ memcpy(&word, sign_bits + i / 8, sizeof(word));
617
+ const __m256i signs = _mm256_set1_epi32(static_cast<int>(word));
618
+ step(acc0, i, signs, positions);
619
+ step(acc1, i + 8, signs, _mm256_slli_epi32(positions, 8));
620
+ step(acc0, i + 16, signs, _mm256_slli_epi32(positions, 16));
621
+ step(acc1, i + 24, signs, _mm256_slli_epi32(positions, 24));
622
+ }
623
+ for (; i + 8 <= d; i += 8) {
624
+ step(acc0, i, _mm256_set1_epi32(sign_bits[i / 8]), positions);
625
+ }
626
+ return hsum_avx2(_mm256_add_ps(acc0, acc1)) +
627
+ ip_scalar(sign_bits, ex_code, rotated_q, i, d, ex_bits, cb);
628
+ }
586
629
  if (ex_bits == 1) {
587
630
  return ip_1exbit_avx2(sign_bits, ex_code, rotated_q, d, cb);
588
631
  }
589
632
 
590
- #ifdef __BMI2__
591
633
  if (ex_bits <= 7) {
592
634
  return ip_bitplane_avx2(sign_bits, ex_code, rotated_q, d, ex_bits, cb);
593
635
  }
594
- #endif
595
636
  return ip_scalar(sign_bits, ex_code, rotated_q, 0, d, ex_bits, cb);
596
637
  }
597
638
 
598
639
  } // namespace faiss::rabitq::multibit
599
-
600
- #endif // COMPILE_SIMD_AVX2