目前,RISC-V 软件分发由于碎片化的生态存在诸多问题:
- rv64gc base 较弱,新的处理器实现了诸如 Bitmanip、Vector、Zicond 扩展提升了性能,但软件难以直接利用
- 现有的带 Vector 的硬件在现有编译器(包括 GCC 15.0)开启 V 扩展后,在部分应用出现了显著的性能提升,但也在部分应用出现了显著的性能下降
- 大家希望 RVA23 可以提供一个良好的平台,但在没有硬件的当下难以对其性能进行评估
经过观察我们发现,大多数程序中的性能热点函数较为集中,因此我们在函数粒度进行多版本的控制,在运行时根据目标机器的情况选择合适的版本,可以较好地解决这一问题。然而,现有的编译器基于 __attribute__((target_clones("default", "arch=+zba,+zbb", "arch=+b,+v,+zicond"))) 这样的函数多版本机制存在许多不好用的问题:
- 参数与架构、编译器支持相关,影响代码在架构、编译器之间的可迁移性
- 需要开发者手工实现函数多版本
- 间接调用时容易引入额外开销
为此,我们为这 3 个问题提出了解决方法:
- 为编译器添加新的参数
-ftarget-clones-table,使得开发者可以在一个独立的文件中描述函数多版本,不影响代码的跨平台迁移问题,同时可以在一次写好多版本参数后,直接在打包过程中使用。 - 自动化的函数克隆表的生成:我们提出了一个基于 perf 采样的方法来评估指定函数在不同扩展版本下的性能,使得函数克隆表可以自动生成,无需开发者人工干预。
- 实现可兼容被调用函数的直接调用:在编译器中修改函数调用的逻辑,对于已经实现了多版本的函数,在与当前的函数调用者不存在 ISA 扩展不支持的问题时,可以像之前一样直接调用而无需访问 GOT 表,同时允许编译器像之前一样进行 inline 处理,解决了多版本调用中的开销问题。
在使用 GCC 15.0 + O3 参数在 rv64gcbv_zicond 真机上的实验数据表明,我们利用了大部分这些扩展可以加速的点,还在 SPECCPU 2006 的测试中,实现了比直接编译为 rv64gcbv_zicond 的二进制加速了 8.4%,因为我们避免了那些降低性能的扩展运行在我们的程序中,同时该二进制也保留了 rv64gc 平台的兼容性。
具体详情可以访问项目主页,也欢迎加入我们的交流群: https://rv64.zip
我们还将在 2025 RISC-V 中国峰会的软件与生态系统分论坛上分享我们的成果,欢迎 7月18日下午前来现场收听!