1616
1717namespace faiss {
1818
19+ template <typename Vec, typename Reduce>
20+ static inline float rvv_reduce (
21+ Vec value,
22+ size_t vl,
23+ float identity,
24+ Reduce reduce) {
25+ vfloat32m1_t init = __riscv_vfmv_s_f_f32m1 (identity, 1 );
26+ vfloat32m1_t result = reduce (value, init, vl);
27+ return __riscv_vfmv_f_s_f32m1_f32 (result);
28+ }
29+
30+ static inline size_t rvv_argmin (const float * values, size_t n) {
31+ size_t vlmax = __riscv_vsetvlmax_e32m8 ();
32+ vfloat32m8_t vmin = __riscv_vfmv_v_f_f32m8 (__builtin_inff (), vlmax);
33+ size_t i = 0 ;
34+ while (i < n) {
35+ size_t vl = __riscv_vsetvl_e32m8 (n - i);
36+ vfloat32m8_t vd = __riscv_vle32_v_f32m8 (values + i, vl);
37+ vmin = __riscv_vfmin_vv_f32m8_tu (vmin, vmin, vd, vl);
38+ i += vl;
39+ }
40+ float min_val = rvv_reduce (
41+ vmin, vlmax, __builtin_inff (), __riscv_vfredmin_vs_f32m8_f32m1);
42+ i = 0 ;
43+ while (i < n) {
44+ size_t vl = __riscv_vsetvl_e32m8 (n - i);
45+ vfloat32m8_t vd = __riscv_vle32_v_f32m8 (values + i, vl);
46+ long j = __riscv_vfirst_m_b4 (
47+ __riscv_vmfeq_vf_f32m8_b4 (vd, min_val, vl), vl);
48+ if (j >= 0 )
49+ return i + static_cast <size_t >(j);
50+ i += vl;
51+ }
52+ return n;
53+ }
54+
1955template <>
2056float fvec_norm_L2sqr<SIMDLevel::RISCV_RVV >(const float * x, size_t d) {
2157 size_t vlmax = __riscv_vsetvlmax_e32m8 ();
@@ -27,9 +63,7 @@ float fvec_norm_L2sqr<SIMDLevel::RISCV_RVV>(const float* x, size_t d) {
2763 acc = __riscv_vfmacc_vv_f32m8_tu (acc, vx, vx, vl);
2864 i += vl;
2965 }
30- vfloat32m1_t sum = __riscv_vfmv_s_f_f32m1 (0 .0f , 1 );
31- sum = __riscv_vfredusum_vs_f32m8_f32m1 (acc, sum, vlmax);
32- return __riscv_vfmv_f_s_f32m1_f32 (sum);
66+ return rvv_reduce (acc, vlmax, 0 .0f , __riscv_vfredusum_vs_f32m8_f32m1);
3367}
3468
3569template <>
@@ -48,9 +82,7 @@ float fvec_L2sqr<SIMDLevel::RISCV_RVV>(
4882 acc = __riscv_vfmacc_vv_f32m8_tu (acc, vx, vx, vl);
4983 i += vl;
5084 }
51- vfloat32m1_t sum = __riscv_vfmv_s_f_f32m1 (0 .0f , 1 );
52- sum = __riscv_vfredusum_vs_f32m8_f32m1 (acc, sum, vlmax);
53- return __riscv_vfmv_f_s_f32m1_f32 (sum);
85+ return rvv_reduce (acc, vlmax, 0 .0f , __riscv_vfredusum_vs_f32m8_f32m1);
5486}
5587
5688template <>
@@ -68,9 +100,7 @@ float fvec_inner_product<SIMDLevel::RISCV_RVV>(
68100 acc = __riscv_vfmacc_vv_f32m8_tu (acc, vx, vy, vl);
69101 i += vl;
70102 }
71- vfloat32m1_t sum = __riscv_vfmv_s_f_f32m1 (0 .0f , 1 );
72- sum = __riscv_vfredusum_vs_f32m8_f32m1 (acc, sum, vlmax);
73- return __riscv_vfmv_f_s_f32m1_f32 (sum);
103+ return rvv_reduce (acc, vlmax, 0 .0f , __riscv_vfredusum_vs_f32m8_f32m1);
74104}
75105
76106template <>
@@ -87,9 +117,7 @@ float fvec_L1<SIMDLevel::RISCV_RVV>(const float* x, const float* y, size_t d) {
87117 acc = __riscv_vfadd_vv_f32m8_tu (acc, acc, vx, vl);
88118 i += vl;
89119 }
90- vfloat32m1_t sum = __riscv_vfmv_s_f_f32m1 (0 .0f , 1 );
91- sum = __riscv_vfredusum_vs_f32m8_f32m1 (acc, sum, vlmax);
92- return __riscv_vfmv_f_s_f32m1_f32 (sum);
120+ return rvv_reduce (acc, vlmax, 0 .0f , __riscv_vfredusum_vs_f32m8_f32m1);
93121}
94122
95123template <>
@@ -109,9 +137,7 @@ float fvec_Linf<SIMDLevel::RISCV_RVV>(
109137 vmax = __riscv_vfmax_vv_f32m8_tu (vmax, vmax, vx, vl);
110138 i += vl;
111139 }
112- vfloat32m1_t max = __riscv_vfmv_s_f_f32m1 (0 .0f , 1 );
113- max = __riscv_vfredmax_vs_f32m8_f32m1 (vmax, max, vlmax);
114- return __riscv_vfmv_f_s_f32m1_f32 (max);
140+ return rvv_reduce (vmax, vlmax, 0 .0f , __riscv_vfredmax_vs_f32m8_f32m1);
115141}
116142
117143template <>
@@ -126,10 +152,29 @@ void fvec_inner_product_batch_4<SIMDLevel::RISCV_RVV>(
126152 float & dis1,
127153 float & dis2,
128154 float & dis3) {
129- dis0 = fvec_inner_product<SIMDLevel::RISCV_RVV >(x, y0, d);
130- dis1 = fvec_inner_product<SIMDLevel::RISCV_RVV >(x, y1, d);
131- dis2 = fvec_inner_product<SIMDLevel::RISCV_RVV >(x, y2, d);
132- dis3 = fvec_inner_product<SIMDLevel::RISCV_RVV >(x, y3, d);
155+ size_t vlmax = __riscv_vsetvlmax_e32m4 ();
156+ vfloat32m4_t vacc0 = __riscv_vfmv_v_f_f32m4 (0 .0f , vlmax);
157+ vfloat32m4_t vacc1 = __riscv_vfmv_v_f_f32m4 (0 .0f , vlmax);
158+ vfloat32m4_t vacc2 = __riscv_vfmv_v_f_f32m4 (0 .0f , vlmax);
159+ vfloat32m4_t vacc3 = __riscv_vfmv_v_f_f32m4 (0 .0f , vlmax);
160+ size_t i = 0 ;
161+ while (i < d) {
162+ size_t vl = __riscv_vsetvl_e32m4 (d - i);
163+ vfloat32m4_t vx = __riscv_vle32_v_f32m4 (x + i, vl);
164+ vfloat32m4_t vy = __riscv_vle32_v_f32m4 (y0 + i, vl);
165+ vacc0 = __riscv_vfmacc_vv_f32m4_tu (vacc0, vx, vy, vl);
166+ vy = __riscv_vle32_v_f32m4 (y1 + i, vl);
167+ vacc1 = __riscv_vfmacc_vv_f32m4_tu (vacc1, vx, vy, vl);
168+ vy = __riscv_vle32_v_f32m4 (y2 + i, vl);
169+ vacc2 = __riscv_vfmacc_vv_f32m4_tu (vacc2, vx, vy, vl);
170+ vy = __riscv_vle32_v_f32m4 (y3 + i, vl);
171+ vacc3 = __riscv_vfmacc_vv_f32m4_tu (vacc3, vx, vy, vl);
172+ i += vl;
173+ }
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);
133178}
134179
135180template <>
@@ -144,10 +189,33 @@ void fvec_L2sqr_batch_4<SIMDLevel::RISCV_RVV>(
144189 float & dis1,
145190 float & dis2,
146191 float & dis3) {
147- dis0 = fvec_L2sqr<SIMDLevel::RISCV_RVV >(x, y0, d);
148- dis1 = fvec_L2sqr<SIMDLevel::RISCV_RVV >(x, y1, d);
149- dis2 = fvec_L2sqr<SIMDLevel::RISCV_RVV >(x, y2, d);
150- dis3 = fvec_L2sqr<SIMDLevel::RISCV_RVV >(x, y3, d);
192+ size_t vlmax = __riscv_vsetvlmax_e32m4 ();
193+ vfloat32m4_t vacc0 = __riscv_vfmv_v_f_f32m4 (0 .0f , vlmax);
194+ vfloat32m4_t vacc1 = __riscv_vfmv_v_f_f32m4 (0 .0f , vlmax);
195+ vfloat32m4_t vacc2 = __riscv_vfmv_v_f_f32m4 (0 .0f , vlmax);
196+ vfloat32m4_t vacc3 = __riscv_vfmv_v_f_f32m4 (0 .0f , vlmax);
197+ size_t i = 0 ;
198+ while (i < d) {
199+ size_t vl = __riscv_vsetvl_e32m4 (d - i);
200+ vfloat32m4_t vx = __riscv_vle32_v_f32m4 (x + i, vl);
201+ vfloat32m4_t vy = __riscv_vle32_v_f32m4 (y0 + i, vl);
202+ vy = __riscv_vfsub_vv_f32m4 (vx, vy, vl);
203+ vacc0 = __riscv_vfmacc_vv_f32m4_tu (vacc0, vy, vy, vl);
204+ vy = __riscv_vle32_v_f32m4 (y1 + i, vl);
205+ vy = __riscv_vfsub_vv_f32m4 (vx, vy, vl);
206+ vacc1 = __riscv_vfmacc_vv_f32m4_tu (vacc1, vy, vy, vl);
207+ vy = __riscv_vle32_v_f32m4 (y2 + i, vl);
208+ vy = __riscv_vfsub_vv_f32m4 (vx, vy, vl);
209+ vacc2 = __riscv_vfmacc_vv_f32m4_tu (vacc2, vy, vy, vl);
210+ vy = __riscv_vle32_v_f32m4 (y3 + i, vl);
211+ vy = __riscv_vfsub_vv_f32m4 (vx, vy, vl);
212+ vacc3 = __riscv_vfmacc_vv_f32m4_tu (vacc3, vy, vy, vl);
213+ i += vl;
214+ }
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);
151219}
152220
153221template <>
@@ -168,9 +236,8 @@ void fvec_L2sqr_ny_transposed<SIMDLevel::RISCV_RVV>(
168236 acc = __riscv_vfmacc_vv_f32m8_tu (acc, vx, vx, vl);
169237 i += vl;
170238 }
171- vfloat32m1_t sum = __riscv_vfmv_s_f_f32m1 (0 .0f , 1 );
172- sum = __riscv_vfredusum_vs_f32m8_f32m1 (acc, sum, vlmax);
173- float x_sqlen = __riscv_vfmv_f_s_f32m1_f32 (sum);
239+ float x_sqlen =
240+ rvv_reduce (acc, vlmax, 0 .0f , __riscv_vfredusum_vs_f32m8_f32m1);
174241 i = 0 ;
175242 while (i < ny) {
176243 size_t vl = __riscv_vsetvl_e32m8 (ny - i);
@@ -214,35 +281,6 @@ void fvec_L2sqr_ny<SIMDLevel::RISCV_RVV>(
214281 }
215282}
216283
217- // Index of the first element equal to the minimum of values[0..n), or n when
218- // there is none (e.g. n == 0). Shared by the *_nearest and madd_and_argmin
219- // kernels so the vfmin/vfredmin/vfirst sequence lives in one place.
220- static size_t rvv_argmin (const float * values, size_t n) {
221- size_t vlmax = __riscv_vsetvlmax_e32m8 ();
222- vfloat32m8_t vmin = __riscv_vfmv_v_f_f32m8 (__builtin_inff (), vlmax);
223- size_t i = 0 ;
224- while (i < n) {
225- size_t vl = __riscv_vsetvl_e32m8 (n - i);
226- vfloat32m8_t vd = __riscv_vle32_v_f32m8 (values + i, vl);
227- vmin = __riscv_vfmin_vv_f32m8_tu (vmin, vmin, vd, vl);
228- i += vl;
229- }
230- vfloat32m1_t rmin = __riscv_vfmv_s_f_f32m1 (__builtin_inff (), 1 );
231- rmin = __riscv_vfredmin_vs_f32m8_f32m1 (vmin, rmin, vlmax);
232- float min_val = __riscv_vfmv_f_s_f32m1_f32 (rmin);
233- i = 0 ;
234- while (i < n) {
235- size_t vl = __riscv_vsetvl_e32m8 (n - i);
236- vfloat32m8_t vd = __riscv_vle32_v_f32m8 (values + i, vl);
237- long j = __riscv_vfirst_m_b4 (
238- __riscv_vmfeq_vf_f32m8_b4 (vd, min_val, vl), vl);
239- if (j >= 0 )
240- return i + static_cast <size_t >(j);
241- i += vl;
242- }
243- return n;
244- }
245-
246284template <>
247285size_t fvec_L2sqr_ny_nearest<SIMDLevel::RISCV_RVV >(
248286 float * distances_tmp_buffer,
0 commit comments