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
@@ -9,13 +9,22 @@
9
9
 
10
10
  #include <faiss/utils/distances.h>
11
11
 
12
- #ifdef COMPILE_SIMD_RISCV_RVV
13
-
12
+ #include <faiss/impl/FaissAssert.h>
14
13
  #include <faiss/utils/extra_distances.h>
15
14
  #include <riscv_vector.h>
16
15
 
16
+ #include <faiss/utils/simd_impl/distances_rvv_kernel.h>
17
+ #include <vector>
18
+
17
19
  namespace faiss {
18
20
 
21
+ // Clang rejects a builtin used as a function argument, so wrap the call in a
22
+ // lambda. GCC accepts the bare name; the wrapper compiles on both.
23
+ #define FAISS_RVV_REDUCE_OP(intrinsic) \
24
+ [](auto value_, auto init_, size_t vl_) { \
25
+ return intrinsic(value_, init_, vl_); \
26
+ }
27
+
19
28
  template <typename Vec, typename Reduce>
20
29
  static inline float rvv_reduce(
21
30
  Vec value,
@@ -38,7 +47,10 @@ static inline size_t rvv_argmin(const float* values, size_t n) {
38
47
  i += vl;
39
48
  }
40
49
  float min_val = rvv_reduce(
41
- vmin, vlmax, __builtin_inff(), __riscv_vfredmin_vs_f32m8_f32m1);
50
+ vmin,
51
+ vlmax,
52
+ __builtin_inff(),
53
+ FAISS_RVV_REDUCE_OP(__riscv_vfredmin_vs_f32m8_f32m1));
42
54
  i = 0;
43
55
  while (i < n) {
44
56
  size_t vl = __riscv_vsetvl_e32m8(n - i);
@@ -52,6 +64,126 @@ static inline size_t rvv_argmin(const float* values, size_t n) {
52
64
  return n;
53
65
  }
54
66
 
67
+ // Write the ksub table entries of one subquantizer that has dsub = 2.
68
+ // The function computes one of these 2 results:
69
+ // inner product: out[k] = x0 * c0[k] + x1 * c1[k]
70
+ // L2: out[k] = (c0[k] - x0)^2 + (c1[k] - x1)^2
71
+ template <bool is_inner_product>
72
+ static inline void rvv_pq2_row(
73
+ const float* c0,
74
+ const float* c1,
75
+ float x0,
76
+ float x1,
77
+ size_t ksub,
78
+ size_t vl,
79
+ float* out) {
80
+ for (size_t k = 0; k < ksub; k += vl) {
81
+ vfloat32m1_t vc0 = __riscv_vle32_v_f32m1(c0 + k, vl);
82
+ vfloat32m1_t vc1 = __riscv_vle32_v_f32m1(c1 + k, vl);
83
+ if constexpr (is_inner_product) {
84
+ vfloat32m1_t r = __riscv_vfmacc_vf_f32m1(
85
+ __riscv_vfmul_vf_f32m1(vc0, x0, vl), x1, vc1, vl);
86
+ __riscv_vse32_v_f32m1(out + k, r, vl);
87
+ } else {
88
+ vfloat32m1_t d0 = __riscv_vfsub_vf_f32m1(vc0, x0, vl);
89
+ vfloat32m1_t d1 = __riscv_vfsub_vf_f32m1(vc1, x1, vl);
90
+ d0 = __riscv_vfmul_vv_f32m1(d0, d0, vl);
91
+ d1 = __riscv_vfmul_vv_f32m1(d1, d1, vl);
92
+ vfloat32m1_t r = __riscv_vfadd_vv_f32m1(d0, d1, vl);
93
+ __riscv_vse32_v_f32m1(out + k, r, vl);
94
+ }
95
+ }
96
+ }
97
+
98
+ template <bool is_inner_product>
99
+ static void rvv_pq2_tables(
100
+ size_t M,
101
+ size_t ksub,
102
+ const float* c0_all,
103
+ const float* c1_all,
104
+ size_t nx,
105
+ const float* x,
106
+ size_t vl,
107
+ float* dis_tables) {
108
+ const size_t d = 2 * M;
109
+ for (size_t i = 0; i < nx; i++) {
110
+ const float* xi = x + i * d;
111
+ float* oi = dis_tables + i * M * ksub;
112
+ size_t m = 0;
113
+ // The loop computes 2 subquantizers per iteration. The 2 computations
114
+ // are independent, so the processor can run them at the same time.
115
+ for (; m + 1 < M; m += 2) {
116
+ rvv_pq2_row<is_inner_product>(
117
+ c0_all + m * ksub,
118
+ c1_all + m * ksub,
119
+ xi[2 * m],
120
+ xi[2 * m + 1],
121
+ ksub,
122
+ vl,
123
+ oi + m * ksub);
124
+ rvv_pq2_row<is_inner_product>(
125
+ c0_all + (m + 1) * ksub,
126
+ c1_all + (m + 1) * ksub,
127
+ xi[2 * (m + 1)],
128
+ xi[2 * (m + 1) + 1],
129
+ ksub,
130
+ vl,
131
+ oi + (m + 1) * ksub);
132
+ }
133
+ // If M is odd, the loop above skips the last subquantizer. This loop
134
+ // computes it.
135
+ for (; m < M; m++) {
136
+ rvv_pq2_row<is_inner_product>(
137
+ c0_all + m * ksub,
138
+ c1_all + m * ksub,
139
+ xi[2 * m],
140
+ xi[2 * m + 1],
141
+ ksub,
142
+ vl,
143
+ oi + m * ksub);
144
+ }
145
+ }
146
+ }
147
+
148
+ template <>
149
+ void compute_PQ_dis_tables_dsub2<SIMDLevel::RISCV_RVV>(
150
+ size_t d,
151
+ size_t ksub,
152
+ const float* all_centroids,
153
+ size_t nx,
154
+ const float* x,
155
+ bool is_inner_product,
156
+ float* dis_tables) {
157
+ const size_t M = d / 2;
158
+ FAISS_THROW_IF_NOT(ksub % 8 == 0);
159
+
160
+ // Separate the centroids into 2 planes. Each plane holds one component of
161
+ // every centroid, so a unit-stride load can read the plane.
162
+ std::vector<float> c0_all(M * ksub);
163
+ std::vector<float> c1_all(M * ksub);
164
+ for (size_t m = 0; m < M; m++) {
165
+ const float* cm = all_centroids + m * ksub * 2;
166
+ float* c0m = c0_all.data() + m * ksub;
167
+ float* c1m = c1_all.data() + m * ksub;
168
+ for (size_t k = 0; k < ksub; k++) {
169
+ c0m[k] = cm[2 * k];
170
+ c1m[k] = cm[2 * k + 1];
171
+ }
172
+ }
173
+
174
+ // ksub is a power of 2, and ksub is a multiple of 8. Therefore vl divides
175
+ // ksub exactly.
176
+ const size_t vl = __riscv_vsetvl_e32m1(ksub);
177
+
178
+ if (is_inner_product) {
179
+ rvv_pq2_tables<true>(
180
+ M, ksub, c0_all.data(), c1_all.data(), nx, x, vl, dis_tables);
181
+ } else {
182
+ rvv_pq2_tables<false>(
183
+ M, ksub, c0_all.data(), c1_all.data(), nx, x, vl, dis_tables);
184
+ }
185
+ }
186
+
55
187
  template <>
56
188
  float fvec_norm_L2sqr<SIMDLevel::RISCV_RVV>(const float* x, size_t d) {
57
189
  size_t vlmax = __riscv_vsetvlmax_e32m8();
@@ -63,7 +195,11 @@ float fvec_norm_L2sqr<SIMDLevel::RISCV_RVV>(const float* x, size_t d) {
63
195
  acc = __riscv_vfmacc_vv_f32m8_tu(acc, vx, vx, vl);
64
196
  i += vl;
65
197
  }
66
- return rvv_reduce(acc, vlmax, 0.0f, __riscv_vfredusum_vs_f32m8_f32m1);
198
+ return rvv_reduce(
199
+ acc,
200
+ vlmax,
201
+ 0.0f,
202
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m8_f32m1));
67
203
  }
68
204
 
69
205
  template <>
@@ -71,18 +207,7 @@ float fvec_L2sqr<SIMDLevel::RISCV_RVV>(
71
207
  const float* x,
72
208
  const float* y,
73
209
  size_t d) {
74
- size_t vlmax = __riscv_vsetvlmax_e32m8();
75
- vfloat32m8_t acc = __riscv_vfmv_v_f_f32m8(0.0f, vlmax);
76
- size_t i = 0;
77
- while (i < d) {
78
- size_t vl = __riscv_vsetvl_e32m8(d - i);
79
- vfloat32m8_t vx = __riscv_vle32_v_f32m8(x + i, vl);
80
- vfloat32m8_t vy = __riscv_vle32_v_f32m8(y + i, vl);
81
- vx = __riscv_vfsub_vv_f32m8(vx, vy, vl);
82
- acc = __riscv_vfmacc_vv_f32m8_tu(acc, vx, vx, vl);
83
- i += vl;
84
- }
85
- return rvv_reduce(acc, vlmax, 0.0f, __riscv_vfredusum_vs_f32m8_f32m1);
210
+ return rvv_kernel::l2_sqr(x, y, d);
86
211
  }
87
212
 
88
213
  template <>
@@ -90,17 +215,7 @@ float fvec_inner_product<SIMDLevel::RISCV_RVV>(
90
215
  const float* x,
91
216
  const float* y,
92
217
  size_t d) {
93
- size_t vlmax = __riscv_vsetvlmax_e32m8();
94
- vfloat32m8_t acc = __riscv_vfmv_v_f_f32m8(0.0f, vlmax);
95
- size_t i = 0;
96
- while (i < d) {
97
- size_t vl = __riscv_vsetvl_e32m8(d - i);
98
- vfloat32m8_t vx = __riscv_vle32_v_f32m8(x + i, vl);
99
- vfloat32m8_t vy = __riscv_vle32_v_f32m8(y + i, vl);
100
- acc = __riscv_vfmacc_vv_f32m8_tu(acc, vx, vy, vl);
101
- i += vl;
102
- }
103
- return rvv_reduce(acc, vlmax, 0.0f, __riscv_vfredusum_vs_f32m8_f32m1);
218
+ return rvv_kernel::inner_product(x, y, d);
104
219
  }
105
220
 
106
221
  template <>
@@ -117,7 +232,11 @@ float fvec_L1<SIMDLevel::RISCV_RVV>(const float* x, const float* y, size_t d) {
117
232
  acc = __riscv_vfadd_vv_f32m8_tu(acc, acc, vx, vl);
118
233
  i += vl;
119
234
  }
120
- return rvv_reduce(acc, vlmax, 0.0f, __riscv_vfredusum_vs_f32m8_f32m1);
235
+ return rvv_reduce(
236
+ acc,
237
+ vlmax,
238
+ 0.0f,
239
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m8_f32m1));
121
240
  }
122
241
 
123
242
  template <>
@@ -137,7 +256,11 @@ float fvec_Linf<SIMDLevel::RISCV_RVV>(
137
256
  vmax = __riscv_vfmax_vv_f32m8_tu(vmax, vmax, vx, vl);
138
257
  i += vl;
139
258
  }
140
- return rvv_reduce(vmax, vlmax, 0.0f, __riscv_vfredmax_vs_f32m8_f32m1);
259
+ return rvv_reduce(
260
+ vmax,
261
+ vlmax,
262
+ 0.0f,
263
+ FAISS_RVV_REDUCE_OP(__riscv_vfredmax_vs_f32m8_f32m1));
141
264
  }
142
265
 
143
266
  template <>
@@ -171,10 +294,26 @@ void fvec_inner_product_batch_4<SIMDLevel::RISCV_RVV>(
171
294
  vacc3 = __riscv_vfmacc_vv_f32m4_tu(vacc3, vx, vy, vl);
172
295
  i += vl;
173
296
  }
174
- dis0 = rvv_reduce(vacc0, vlmax, 0.0f, __riscv_vfredusum_vs_f32m4_f32m1);
175
- dis1 = rvv_reduce(vacc1, vlmax, 0.0f, __riscv_vfredusum_vs_f32m4_f32m1);
176
- dis2 = rvv_reduce(vacc2, vlmax, 0.0f, __riscv_vfredusum_vs_f32m4_f32m1);
177
- dis3 = rvv_reduce(vacc3, vlmax, 0.0f, __riscv_vfredusum_vs_f32m4_f32m1);
297
+ dis0 = rvv_reduce(
298
+ vacc0,
299
+ vlmax,
300
+ 0.0f,
301
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m4_f32m1));
302
+ dis1 = rvv_reduce(
303
+ vacc1,
304
+ vlmax,
305
+ 0.0f,
306
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m4_f32m1));
307
+ dis2 = rvv_reduce(
308
+ vacc2,
309
+ vlmax,
310
+ 0.0f,
311
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m4_f32m1));
312
+ dis3 = rvv_reduce(
313
+ vacc3,
314
+ vlmax,
315
+ 0.0f,
316
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m4_f32m1));
178
317
  }
179
318
 
180
319
  template <>
@@ -212,10 +351,26 @@ void fvec_L2sqr_batch_4<SIMDLevel::RISCV_RVV>(
212
351
  vacc3 = __riscv_vfmacc_vv_f32m4_tu(vacc3, vy, vy, vl);
213
352
  i += vl;
214
353
  }
215
- dis0 = rvv_reduce(vacc0, vlmax, 0.0f, __riscv_vfredusum_vs_f32m4_f32m1);
216
- dis1 = rvv_reduce(vacc1, vlmax, 0.0f, __riscv_vfredusum_vs_f32m4_f32m1);
217
- dis2 = rvv_reduce(vacc2, vlmax, 0.0f, __riscv_vfredusum_vs_f32m4_f32m1);
218
- dis3 = rvv_reduce(vacc3, vlmax, 0.0f, __riscv_vfredusum_vs_f32m4_f32m1);
354
+ dis0 = rvv_reduce(
355
+ vacc0,
356
+ vlmax,
357
+ 0.0f,
358
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m4_f32m1));
359
+ dis1 = rvv_reduce(
360
+ vacc1,
361
+ vlmax,
362
+ 0.0f,
363
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m4_f32m1));
364
+ dis2 = rvv_reduce(
365
+ vacc2,
366
+ vlmax,
367
+ 0.0f,
368
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m4_f32m1));
369
+ dis3 = rvv_reduce(
370
+ vacc3,
371
+ vlmax,
372
+ 0.0f,
373
+ FAISS_RVV_REDUCE_OP(__riscv_vfredusum_vs_f32m4_f32m1));
219
374
  }
220
375
 
221
376
  template <>
@@ -227,31 +382,56 @@ void fvec_L2sqr_ny_transposed<SIMDLevel::RISCV_RVV>(
227
382
  size_t d,
228
383
  size_t d_offset,
229
384
  size_t ny) {
230
- size_t vlmax = __riscv_vsetvlmax_e32m8();
231
- vfloat32m8_t acc = __riscv_vfmv_v_f_f32m8(0.0f, vlmax);
385
+ // Compute the squared length of the query subvector.
386
+ float x_sqlen = 0;
387
+ for (size_t j = 0; j < d; j++) {
388
+ x_sqlen += x[j] * x[j];
389
+ }
390
+
391
+ // The loop below divides the ny dimension into chunks. Each chunk uses
392
+ // e32m8. The chunk size is VLMAX, so the kernel fills the whole vector
393
+ // register at every VLEN.
394
+ const size_t chunk = __riscv_vsetvlmax_e32m8();
232
395
  size_t i = 0;
233
- while (i < d) {
234
- size_t vl = __riscv_vsetvl_e32m8(d - i);
235
- vfloat32m8_t vx = __riscv_vle32_v_f32m8(x + i, vl);
236
- acc = __riscv_vfmacc_vv_f32m8_tu(acc, vx, vx, vl);
237
- i += vl;
396
+
397
+ // dis[i] = x_sqlen + y_sqlen[i] - 2 * sum_j x[j] * y[j * d_offset + i]
398
+ //
399
+ // The code accumulates the dot product first, and it applies the factor
400
+ // of 2 afterwards. Matches SIMDLevel::NONE implementation which scales the
401
+ // accumulated dot product in the same way.
402
+ for (; i + chunk <= ny; i += chunk) {
403
+ vfloat32m8_t dp = __riscv_vfmv_v_f_f32m8(0.0f, chunk);
404
+ for (size_t j = 0; j < d; j++) {
405
+ vfloat32m8_t y_vec =
406
+ __riscv_vle32_v_f32m8(y + j * d_offset + i, chunk);
407
+ dp = __riscv_vfmacc_vf_f32m8(dp, x[j], y_vec, chunk);
408
+ }
409
+
410
+ vfloat32m8_t acc = __riscv_vle32_v_f32m8(y_sqlen + i, chunk);
411
+ acc = __riscv_vfadd_vf_f32m8(acc, x_sqlen, chunk);
412
+ dp = __riscv_vfmul_vf_f32m8(dp, 2.0f, chunk);
413
+ acc = __riscv_vfsub_vv_f32m8(acc, dp, chunk);
414
+
415
+ __riscv_vse32_v_f32m8(dis + i, acc, chunk);
238
416
  }
239
- float x_sqlen =
240
- rvv_reduce(acc, vlmax, 0.0f, __riscv_vfredusum_vs_f32m8_f32m1);
241
- i = 0;
242
- while (i < ny) {
417
+
418
+ // This block computes the last ny % chunk elements.
419
+ if (i < ny) {
243
420
  size_t vl = __riscv_vsetvl_e32m8(ny - i);
244
- acc = __riscv_vfmv_v_f_f32m8(0.0f, vl);
421
+
422
+ vfloat32m8_t dp = __riscv_vfmv_v_f_f32m8(0.0f, vl);
245
423
  for (size_t j = 0; j < d; j++) {
246
- vfloat32m8_t vy = __riscv_vle32_v_f32m8(y + j * d_offset + i, vl);
247
- acc = __riscv_vfmacc_vf_f32m8(acc, x[j], vy, vl);
424
+ vfloat32m8_t y_vec =
425
+ __riscv_vle32_v_f32m8(y + j * d_offset + i, vl);
426
+ dp = __riscv_vfmacc_vf_f32m8(dp, x[j], y_vec, vl);
248
427
  }
249
- vfloat32m8_t vres = __riscv_vle32_v_f32m8(y_sqlen + i, vl);
250
- vres = __riscv_vfadd_vf_f32m8(vres, x_sqlen, vl);
251
- acc = __riscv_vfmul_vf_f32m8(acc, 2.0f, vl);
252
- vres = __riscv_vfsub_vv_f32m8(vres, acc, vl);
253
- __riscv_vse32_v_f32m8(dis + i, vres, vl);
254
- i += vl;
428
+
429
+ vfloat32m8_t acc = __riscv_vle32_v_f32m8(y_sqlen + i, vl);
430
+ acc = __riscv_vfadd_vf_f32m8(acc, x_sqlen, vl);
431
+ dp = __riscv_vfmul_vf_f32m8(dp, 2.0f, vl);
432
+ acc = __riscv_vfsub_vv_f32m8(acc, dp, vl);
433
+
434
+ __riscv_vse32_v_f32m8(dis + i, acc, vl);
255
435
  }
256
436
  }
257
437
 
@@ -262,9 +442,40 @@ void fvec_inner_products_ny<SIMDLevel::RISCV_RVV>(
262
442
  const float* y,
263
443
  size_t d,
264
444
  size_t ny) {
265
- for (size_t i = 0; i < ny; i++) {
266
- ip[i] = fvec_inner_product<SIMDLevel::RISCV_RVV>(x, y, d);
267
- y += d;
445
+ // The loop below divides the ny dimension into chunks. Each chunk uses
446
+ // e32m4.
447
+ // ip[i] = sum_{j=0}^{d-1} x[j] * y[i * d + j]
448
+ const size_t chunk = __riscv_vsetvlmax_e32m4();
449
+ const ptrdiff_t stride_bytes = (ptrdiff_t)d * (ptrdiff_t)sizeof(float);
450
+ size_t i = 0;
451
+
452
+ for (; i + chunk <= ny; i += chunk) {
453
+ vfloat32m4_t acc = __riscv_vfmv_v_f_f32m4(0.0f, chunk);
454
+ const float* yb = y + i * d; // the first vector of this chunk
455
+
456
+ for (size_t j = 0; j < d; j++) {
457
+ vfloat32m4_t y_vec =
458
+ __riscv_vlse32_v_f32m4(yb + j, stride_bytes, chunk);
459
+ acc = __riscv_vfmacc_vf_f32m4(acc, x[j], y_vec, chunk);
460
+ }
461
+
462
+ __riscv_vse32_v_f32m4(ip + i, acc, chunk);
463
+ }
464
+
465
+ // This block computes the last ny % chunk elements.
466
+ if (i < ny) {
467
+ size_t vl = __riscv_vsetvl_e32m4(ny - i);
468
+
469
+ vfloat32m4_t acc = __riscv_vfmv_v_f_f32m4(0.0f, vl);
470
+ const float* yb = y + i * d;
471
+
472
+ for (size_t j = 0; j < d; j++) {
473
+ vfloat32m4_t y_vec =
474
+ __riscv_vlse32_v_f32m4(yb + j, stride_bytes, vl);
475
+ acc = __riscv_vfmacc_vf_f32m4(acc, x[j], y_vec, vl);
476
+ }
477
+
478
+ __riscv_vse32_v_f32m4(ip + i, acc, vl);
268
479
  }
269
480
  }
270
481
 
@@ -275,9 +486,35 @@ void fvec_L2sqr_ny<SIMDLevel::RISCV_RVV>(
275
486
  const float* y,
276
487
  size_t d,
277
488
  size_t ny) {
278
- for (size_t i = 0; i < ny; i++) {
279
- dis[i] = fvec_L2sqr<SIMDLevel::RISCV_RVV>(x, y, d);
280
- y += d;
489
+ // The loop below divides the ny dimension into chunks. Each chunk uses
490
+ // e32m8.
491
+ const size_t chunk = __riscv_vsetvlmax_e32m8();
492
+ const ptrdiff_t stride_bytes = (ptrdiff_t)d * (ptrdiff_t)sizeof(float);
493
+ size_t i = 0;
494
+
495
+ for (; i + chunk <= ny; i += chunk) {
496
+ vfloat32m8_t acc = __riscv_vfmv_v_f_f32m8(0.0f, chunk);
497
+ const float* yb = y + i * d; // the first vector of this chunk
498
+ for (size_t j = 0; j < d; j++) {
499
+ vfloat32m8_t y_vec =
500
+ __riscv_vlse32_v_f32m8(yb + j, stride_bytes, chunk);
501
+ vfloat32m8_t diff = __riscv_vfsub_vf_f32m8(y_vec, x[j], chunk);
502
+ acc = __riscv_vfmacc_vv_f32m8(acc, diff, diff, chunk);
503
+ }
504
+ __riscv_vse32_v_f32m8(dis + i, acc, chunk);
505
+ }
506
+
507
+ if (i < ny) {
508
+ size_t vl = __riscv_vsetvl_e32m8(ny - i);
509
+ vfloat32m8_t acc = __riscv_vfmv_v_f_f32m8(0.0f, vl);
510
+ const float* yb = y + i * d;
511
+ for (size_t j = 0; j < d; j++) {
512
+ vfloat32m8_t y_vec =
513
+ __riscv_vlse32_v_f32m8(yb + j, stride_bytes, vl);
514
+ vfloat32m8_t diff = __riscv_vfsub_vf_f32m8(y_vec, x[j], vl);
515
+ acc = __riscv_vfmacc_vv_f32m8(acc, diff, diff, vl);
516
+ }
517
+ __riscv_vse32_v_f32m8(dis + i, acc, vl);
281
518
  }
282
519
  }
283
520
 
@@ -288,9 +525,8 @@ size_t fvec_L2sqr_ny_nearest<SIMDLevel::RISCV_RVV>(
288
525
  const float* y,
289
526
  size_t d,
290
527
  size_t ny) {
291
- fvec_L2sqr_ny<SIMDLevel::RISCV_RVV>(distances_tmp_buffer, x, y, d, ny);
292
- const size_t j = rvv_argmin(distances_tmp_buffer, ny);
293
- return j < ny ? j : 0;
528
+ return fvec_L2sqr_ny_nearest<SIMDLevel::NONE>(
529
+ distances_tmp_buffer, x, y, d, ny);
294
530
  }
295
531
 
296
532
  template <>
@@ -302,10 +538,8 @@ size_t fvec_L2sqr_ny_nearest_y_transposed<SIMDLevel::RISCV_RVV>(
302
538
  size_t d,
303
539
  size_t d_offset,
304
540
  size_t ny) {
305
- fvec_L2sqr_ny_transposed<SIMDLevel::RISCV_RVV>(
541
+ return fvec_L2sqr_ny_nearest_y_transposed<SIMDLevel::NONE>(
306
542
  distances_tmp_buffer, x, y, y_sqlen, d, d_offset, ny);
307
- const size_t j = rvv_argmin(distances_tmp_buffer, ny);
308
- return j < ny ? j : 0;
309
543
  }
310
544
 
311
545
  template <>
@@ -338,6 +572,56 @@ int fvec_madd_and_argmin<SIMDLevel::RISCV_RVV>(
338
572
  return j < n ? static_cast<int>(j) : -1;
339
573
  }
340
574
 
575
+ template <>
576
+ void fvec_add<SIMDLevel::RISCV_RVV>(
577
+ size_t d,
578
+ const float* a,
579
+ const float* b,
580
+ float* c) {
581
+ size_t i = 0;
582
+ while (i < d) {
583
+ size_t vl = __riscv_vsetvl_e32m8(d - i);
584
+ vfloat32m8_t va = __riscv_vle32_v_f32m8(a + i, vl);
585
+ vfloat32m8_t vb = __riscv_vle32_v_f32m8(b + i, vl);
586
+ va = __riscv_vfadd_vv_f32m8(va, vb, vl);
587
+ __riscv_vse32_v_f32m8(c + i, va, vl);
588
+ i += vl;
589
+ }
590
+ }
591
+
592
+ template <>
593
+ void fvec_add<SIMDLevel::RISCV_RVV>(
594
+ size_t d,
595
+ const float* a,
596
+ float b,
597
+ float* c) {
598
+ size_t i = 0;
599
+ while (i < d) {
600
+ size_t vl = __riscv_vsetvl_e32m8(d - i);
601
+ vfloat32m8_t va = __riscv_vle32_v_f32m8(a + i, vl);
602
+ va = __riscv_vfadd_vf_f32m8(va, b, vl);
603
+ __riscv_vse32_v_f32m8(c + i, va, vl);
604
+ i += vl;
605
+ }
606
+ }
607
+
608
+ template <>
609
+ void fvec_sub<SIMDLevel::RISCV_RVV>(
610
+ size_t d,
611
+ const float* a,
612
+ const float* b,
613
+ float* c) {
614
+ size_t i = 0;
615
+ while (i < d) {
616
+ size_t vl = __riscv_vsetvl_e32m8(d - i);
617
+ vfloat32m8_t va = __riscv_vle32_v_f32m8(a + i, vl);
618
+ vfloat32m8_t vb = __riscv_vle32_v_f32m8(b + i, vl);
619
+ va = __riscv_vfsub_vv_f32m8(va, vb, vl);
620
+ __riscv_vse32_v_f32m8(c + i, va, vl);
621
+ i += vl;
622
+ }
623
+ }
624
+
341
625
  #define DEFINE_VECTOR_DISTANCE_RVV_FALLBACK(metric) \
342
626
  template <> \
343
627
  float VectorDistance<metric, SIMDLevel::RISCV_RVV>::operator()( \
@@ -365,5 +649,3 @@ DEFINE_VECTOR_DISTANCE_RVV_FALLBACK(METRIC_GOWER)
365
649
  #define THE_SIMD_LEVEL SIMDLevel::RISCV_RVV
366
650
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
367
651
  #include <faiss/utils/simd_impl/IVFFlatScanner-inl.h>
368
-
369
- #endif // COMPILE_SIMD_RISCV_RVV
@@ -0,0 +1,68 @@
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
+ /* Vector-to-vector distance kernels for RISC-V Vector.
11
+ *
12
+ * Free-standing (no exceptions, heap or threads), so a freestanding RISC-V
13
+ * target can compile it. distances_rvv.cpp calls these; no Buck target here
14
+ * builds that RISC-V CPU path.
15
+ *
16
+ * These inline the horizontal reduction rather than passing the intrinsic to
17
+ * a helper. Clang rejects a builtin used as a function argument.
18
+ *
19
+ * They accumulate at LMUL 4, not 8: a group of eight leaves only four
20
+ * register groups, which is slower in a scan loop. The order of the
21
+ * additions differs from LMUL 8, so the last bits can differ.
22
+
23
+ */
24
+
25
+ #include <cstddef>
26
+
27
+ #include <riscv_vector.h>
28
+
29
+ namespace faiss {
30
+ namespace rvv_kernel {
31
+
32
+ /// Squared L2 distance between two fp32 vectors.
33
+ inline float l2_sqr(const float* x, const float* y, size_t d) {
34
+ const size_t vlmax = __riscv_vsetvlmax_e32m4();
35
+ vfloat32m4_t acc = __riscv_vfmv_v_f_f32m4(0.0f, vlmax);
36
+ size_t i = 0;
37
+ while (i < d) {
38
+ const size_t vl = __riscv_vsetvl_e32m4(d - i);
39
+ vfloat32m4_t vx = __riscv_vle32_v_f32m4(x + i, vl);
40
+ vfloat32m4_t vy = __riscv_vle32_v_f32m4(y + i, vl);
41
+ vx = __riscv_vfsub_vv_f32m4(vx, vy, vl);
42
+ acc = __riscv_vfmacc_vv_f32m4_tu(acc, vx, vx, vl);
43
+ i += vl;
44
+ }
45
+ vfloat32m1_t init = __riscv_vfmv_s_f_f32m1(0.0f, 1);
46
+ vfloat32m1_t r = __riscv_vfredusum_vs_f32m4_f32m1(acc, init, vlmax);
47
+ return __riscv_vfmv_f_s_f32m1_f32(r);
48
+ }
49
+
50
+ /// Inner product of two fp32 vectors.
51
+ inline float inner_product(const float* x, const float* y, size_t d) {
52
+ const size_t vlmax = __riscv_vsetvlmax_e32m4();
53
+ vfloat32m4_t acc = __riscv_vfmv_v_f_f32m4(0.0f, vlmax);
54
+ size_t i = 0;
55
+ while (i < d) {
56
+ const size_t vl = __riscv_vsetvl_e32m4(d - i);
57
+ vfloat32m4_t vx = __riscv_vle32_v_f32m4(x + i, vl);
58
+ vfloat32m4_t vy = __riscv_vle32_v_f32m4(y + i, vl);
59
+ acc = __riscv_vfmacc_vv_f32m4_tu(acc, vx, vy, vl);
60
+ i += vl;
61
+ }
62
+ vfloat32m1_t init = __riscv_vfmv_s_f_f32m1(0.0f, 1);
63
+ vfloat32m1_t r = __riscv_vfredusum_vs_f32m4_f32m1(acc, init, vlmax);
64
+ return __riscv_vfmv_f_s_f32m1_f32(r);
65
+ }
66
+
67
+ } // namespace rvv_kernel
68
+ } // namespace faiss