Page 84 - 《软件学报》2025年第9期
P. 84
韩柳彤 等: 面向 RISC-V 向量扩展的高性能算法库优化方法 3995
的类型封装部分, 不再引入包装类, 而是直接采用类型别名的方式将 RISC-V 向量扩展的内建向量类型映射为通
用内建函数所定义的向量类型. 使用类型别名省去了包装类型到内建类型的转换, 能够避免产生冗余访存指令, 因
此更为高效. 其次, 为了承载向量类型的元数据, 引入了特征类. 这是因为在定长的通用内建函数设计中, 向量类型
元数据作为类成员被包含在包装类中, 而本文提出的设计方案不再使用包装类型, 引入新的特征类承载向量类型
的元数据并提供访问接口是必要的; 此外, 在函数封装方面, 引入了新的函数接口定义, 代替现有实现中依赖于包
装类的运算符重载函数. 最后, 为其他平台新引入了兼容层, 使新引入的特征类和通用内建函数设计可以顺利映射
到其他平台已有的实现上, 并面向开发人员提供一致的通用内建函数编程接口.
OpenCV 通用内建函数
本文提出的通用内建函数编程接口
兼容层
特征类 新函数
原有
封装类的
原有成员 重载函数 通用内建函数 特征类 新函数
(除重载函数)
面向原有固定长度平台的接口 面向新增可变长平台的接口
图 4 面向可变长体系结构的通用内建函数编程接口设计
尽管本文的设计方案与现有方案在功能上保持一致, 但也存在上述由取消包装类而引入的诸多接口变更, 导
致新的通用内建函数编程接口无法向前兼容. 因此, 现有使用通用内建函数所编写的优化代码需要进行部分改写
从而迁移到新编程接口, 我们开发了针对相关接口变更的自动化迁移工具, 并使用新编程接口重构了 OpenCV 代
码仓库中 90.6% 的通用内建函数代码块, 从而使大部分现有的向量优化算法实现得以在 RISC-V 设备上启用, 且
后续使用新编程接口实现的算法优化将能在 RISC-V 平台和其他平台上同步获得性能提升, 有效降低了算法库的
开发复杂度.
3.3.1 利用类型别名消除冗余指令
为了提供统一的编程接口, OpenCV 通用内建函数使用包装类的方式封装了不同向量后端的内建向量类型.
然而, 由于 C++语言的限制, 可变长的 RISC-V 向量扩展的内建向量类型由于缺少编译时的长度信息而无法被包
含在任何类型中. 可选的代替方案是使用数组来存放数据, 同时增加 RISC-V 向量类型和 OpenCV 通用内建函数
向量类型之间的转换函数, 该方案在一定程度上解决了 RISC-V 向量类型与包装类型不兼容的问题. 但两种类型
之间的转换不可避免地使用访存指令实现数组和寄存器的数据交换, 在使用通用内建函数编程时, 每条指令都会
引入两次冗余访存指令, 极大影响执行性能.
因此, 本文提出了使用类型别名代替包装类的方案, 即将 OpenCV 通用内建函数向量类型直接作为 RISC-V
向量类型的别名使用. 在使用通用内建函数的向量类型时, 本质上是在使用 RISC-V 内建的向量类型, 因此省去了
类型转换与对象拷贝的开销. 如表 3 所示, 应用本文方法的 OpenCV 通用内建函数实现所生成的汇编指令中仅包
含通用内建函数所述语义对应向量指令 (表中以不同颜色高亮) 与其他必要指令, 解决了原有实现中产生冗余访
存指令问题.

