1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-21 19:33:03 +04:00

dnn: add RVV LMUL=1 kernel for convBlock_F32 (ConvolutionLayer, rv64gcv)

This commit is contained in:
Teddy-Yangjiale
2026-06-29 00:47:44 +08:00
parent dd541965e9
commit c831290769
@@ -2206,6 +2206,70 @@ void convBlock_F32(int np, const float* a, const float* b, float* c, int ldc, bo
return; return;
} }
convBlockNoSIMD(np, a, b, c, ldc, init_c, outLen, convMR, convNR); convBlockNoSIMD(np, a, b, c, ldc, init_c, outLen, convMR, convNR);
#elif CV_RVV
{
// LMUL=1 kernel: vlanes = VLEN/32 (8 at VLEN=256).
// OpenCV's v_float32 is vfloat32m2_t (LMUL=2, vlanes=2*VLEN/32=16 at VLEN=256);
// 24 % 16 != 0, so the 24-wide tile requires LMUL=1 and native intrinsics.
// vfmacc.vf (scalar-into-vector FMA) avoids a broadcast register.
// Only the exact full-tile case (outLen==convNR) is handled; tails fall to scalar.
const size_t vl = __riscv_vsetvlmax_e32m1();
if (convMR == 4 && (size_t)convNR == 3 * vl && outLen == convNR)
{
vfloat32m1_t c00 = __riscv_vfmv_v_f_f32m1(0.f, vl);
vfloat32m1_t c01 = c00, c02 = c00;
vfloat32m1_t c10 = c00, c11 = c00, c12 = c00;
vfloat32m1_t c20 = c00, c21 = c00, c22 = c00;
vfloat32m1_t c30 = c00, c31 = c00, c32 = c00;
for (int p = 0; p < np; p++, a += convMR, b += convNR)
{
vfloat32m1_t b0 = __riscv_vle32_v_f32m1(b, vl);
vfloat32m1_t b1 = __riscv_vle32_v_f32m1(b + vl, vl);
vfloat32m1_t b2 = __riscv_vle32_v_f32m1(b + 2 * vl, vl);
c00 = __riscv_vfmacc_vf_f32m1(c00, a[0], b0, vl);
c01 = __riscv_vfmacc_vf_f32m1(c01, a[0], b1, vl);
c02 = __riscv_vfmacc_vf_f32m1(c02, a[0], b2, vl);
c10 = __riscv_vfmacc_vf_f32m1(c10, a[1], b0, vl);
c11 = __riscv_vfmacc_vf_f32m1(c11, a[1], b1, vl);
c12 = __riscv_vfmacc_vf_f32m1(c12, a[1], b2, vl);
c20 = __riscv_vfmacc_vf_f32m1(c20, a[2], b0, vl);
c21 = __riscv_vfmacc_vf_f32m1(c21, a[2], b1, vl);
c22 = __riscv_vfmacc_vf_f32m1(c22, a[2], b2, vl);
c30 = __riscv_vfmacc_vf_f32m1(c30, a[3], b0, vl);
c31 = __riscv_vfmacc_vf_f32m1(c31, a[3], b1, vl);
c32 = __riscv_vfmacc_vf_f32m1(c32, a[3], b2, vl);
}
if (!init_c)
{
c00 = __riscv_vfadd_vv_f32m1(c00, __riscv_vle32_v_f32m1(c, vl), vl);
c01 = __riscv_vfadd_vv_f32m1(c01, __riscv_vle32_v_f32m1(c + vl, vl), vl);
c02 = __riscv_vfadd_vv_f32m1(c02, __riscv_vle32_v_f32m1(c + 2 * vl, vl), vl);
c10 = __riscv_vfadd_vv_f32m1(c10, __riscv_vle32_v_f32m1(c + ldc, vl), vl);
c11 = __riscv_vfadd_vv_f32m1(c11, __riscv_vle32_v_f32m1(c + ldc + vl, vl), vl);
c12 = __riscv_vfadd_vv_f32m1(c12, __riscv_vle32_v_f32m1(c + ldc + 2 * vl, vl), vl);
c20 = __riscv_vfadd_vv_f32m1(c20, __riscv_vle32_v_f32m1(c + 2 * ldc, vl), vl);
c21 = __riscv_vfadd_vv_f32m1(c21, __riscv_vle32_v_f32m1(c + 2 * ldc + vl, vl), vl);
c22 = __riscv_vfadd_vv_f32m1(c22, __riscv_vle32_v_f32m1(c + 2 * ldc + 2 * vl, vl), vl);
c30 = __riscv_vfadd_vv_f32m1(c30, __riscv_vle32_v_f32m1(c + 3 * ldc, vl), vl);
c31 = __riscv_vfadd_vv_f32m1(c31, __riscv_vle32_v_f32m1(c + 3 * ldc + vl, vl), vl);
c32 = __riscv_vfadd_vv_f32m1(c32, __riscv_vle32_v_f32m1(c + 3 * ldc + 2 * vl, vl), vl);
}
__riscv_vse32_v_f32m1(c, c00, vl);
__riscv_vse32_v_f32m1(c + vl, c01, vl);
__riscv_vse32_v_f32m1(c + 2 * vl, c02, vl);
__riscv_vse32_v_f32m1(c + ldc, c10, vl);
__riscv_vse32_v_f32m1(c + ldc + vl, c11, vl);
__riscv_vse32_v_f32m1(c + ldc + 2 * vl, c12, vl);
__riscv_vse32_v_f32m1(c + 2 * ldc, c20, vl);
__riscv_vse32_v_f32m1(c + 2 * ldc + vl, c21, vl);
__riscv_vse32_v_f32m1(c + 2 * ldc + 2 * vl, c22, vl);
__riscv_vse32_v_f32m1(c + 3 * ldc, c30, vl);
__riscv_vse32_v_f32m1(c + 3 * ldc + vl, c31, vl);
__riscv_vse32_v_f32m1(c + 3 * ldc + 2 * vl, c32, vl);
return;
}
convBlockNoSIMD(np, a, b, c, ldc, init_c, outLen, convMR, convNR);
}
#else #else
convBlockNoSIMD(np, a, b, c, ldc, init_c, outLen, convMR, convNR); convBlockNoSIMD(np, a, b, c, ldc, init_c, outLen, convMR, convNR);
return; return;