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  向量扩展平台上, 测试并
   80   81   82   83   84   85   86   87   88   89   90