Page 85 - 《软件学报》2025年第9期
P. 85
3996 软件学报 2025 年第 36 卷第 9 期
表 3 应用不同方法实现 OpenCV 通用内建函数所生成的 RISC-V 向量汇编指令对比 (以 saxpy 算法为例)
行 应用本文方法的OpenCV通用内建函数实现 OpenCV原有通用内建函数实现
1 saxpy(unsigned long, float, float const*, float*): saxpy(unsigned long, float, float const*, float*):
2 lui a5,%hi(__cv_rvv_e32m2_nlanes) beq a0,zero,.L10
3 lw a4,%lo(__cv_rvv_e32m2_nlanes)(a5) addi sp,sp,-48
4 li a3,0 li a6,0
5 li a5,0 li a4,0
6 beq a0,zero,.L7 addi a5,sp,32
7 vsetvli zero,a4,e32,m2,ta,ma mv t1,sp
8 .L3: addi a3,sp,16
9 slli a5,a5,2 vsetivli zero,4,e32,m1,ta,ma
10 add a6,a2,a5 .L3:
11 add a7,a1,a5 slli a4,a4,2
12 vle32.v v2,0(a7) # vy = v_load(x+i); add a7,a1,a4
13 vle32.v v1,0(a6) # vy = v_load(y+i); vle32.v v1,0(a7) # vx = v_load(x+i);
14 addw a3,a3,a4 add a7,a2,a4
15 mv a5,a3 addiw a6,a6,4
16 vfmacc.vf v1,fa0,v2 # vy = v_fma(a, vx, vy); mv a4,a6
17 vse32.v v1,0(a6) # v_store(y+i, vy); vse32.v v1,0(a5) # v_load(x+i)的显式类型转换
18 bltu a3,a0,.L3 vle32.v v1,0(a5) # vx 赋值操作拷贝构造(自动向量化)
19 .L7: vse32.v v1,0(t1) # vx 赋值操作拷贝构造(自动向量化)
20 ret vle32.v v1,0(a7) # vy = v_load(y+i);
21 vse32.v v1,0(a5) # v_load(y+i)的显式类型转换
22 vle32.v v1,0(a5) # vy 赋值操作拷贝构造(自动向量化)
23 vse32.v v1,0(a3) # vy 赋值操作拷贝构造(自动向量化)
24 vle32.v v1,0(a3) # v_fma 中 vx 的隐式类型转换
25 vle32.v v2,0(t1) # v_fma 中 vy 的隐式类型转换
26 vfmacc.vf v1,fa0,v2 # vy = v_fma(a, vx, vy);
27 vse32.v v1,0(a5) # vfmacc.vf 的显式类型转换
28 vle32.v v1,0(a5) # vy 赋值操作拷贝构造(自动向量化)
29 vse32.v v1,0(a3) # vy 赋值操作拷贝构造(自动向量化)
30 vle32.v v1,0(a3) # v_store 中 vy 的隐式类型转换
31 vse32.v v1,0(a7) # v_store(y+i, vy);
32 bltu a6,a0,.L3
33 addi sp,sp,48
34 jr ra
35 .L10:
36 ret
3.3.2 特征类、函数封装与兼容性
在 OpenCV 通用内建函数原有的类型封装中, 包含了标量元素个数和元素类型等类型元数据. 由于本文所提
出的新实现方法使用类型别名代替了类型封装, 而且类型元数据无法作为 RISC-V 内建数据类型的成员存在, 因
此只能引入新的类型封装元数据, 称为特征类. 在特征类中, 包含了用于表述向量类型中标量元素类型的成员
lane_type 和表述向量内元素个数的成员函数 vlanes. 特别地, 与其他 SIMD 后端中对函数 vlanes 的调用会返回固
定长度不同, RISC-V 向量后端中 vlanes 通过相应指令在运行时获得向量寄存器所支持的最大元素个数, 从而实现
对 RISC-V 向量扩展的可变向量寄存器长度特性的支持.
类似地, 依托于原有的类型封装, OpenCV 通用内建函数还实现了部分运算符重载, 这在使用类型别名的
RISC-V 后端中也由于语言限制无法实现. 对于这类函数, 本文引入了新的通用内建函数, 实现相同的功能. 例如其
他后端中使用重载运算符“+”实现向量加法, 在 RISC-V 后端中则使用新的通用内建函数“v_add”实现, 代替运算符
重载.
4 实验结果与分析
本节以 OpenCV 算法库作为实验对象, 在两种具有不同向量寄存器长度的 RISC-V 向量扩展平台上, 测试并

