c – 根据支持的说明选择要使用的装配实施

我正在开发一个C库,它编译/链接到.a文件,用户可以静态链接到他们的代码.库的性能非常重要,因此我在x86-64汇编中编写性能关键的例程来优化性能.

对于某些例程,如果使用BMI2指令,我可以获得明显更好的性能,而不是坚持使用“标准”x86-64指令集.麻烦的是,BMI2最近刚推出,我的一些用户使用不支持这些指令的处理器.

所以,我写过两次优化程序,一次使用BMI2指令,一次不使用它们.在我目前的设置中,我将分发两个版本的.a文件一个需要支持BMI2指令的“快速”版本,以及一个不需要支持BMI2指令的“慢”版本.

我问是否有办法通过分发单个.a文件来简化这一过程,该文件将根据最终应用程序运行的cpu是否支持BMI2指令动态选择正确的实现.

与StackOverflow上的类似问题不同,这里有两个特点:

>选择函数的技术需要在关键路径中具有特别低的开销.在汇编优化之后,所讨论的例程在大约10 ns内运行,因此即使单个if语句也可能很重要.
>需要“动态”选择的功能在开始时选择一次,然后在程序的持续时间内保持固定.我希望这将提供比这个问题中建议的更快的解决方案:Choosing method implementation at runtime

我到目前为止提出的最快解决方案是执行以下操作:

>使用cpuid指令检查cpu是否支持BMI2指令.
>根据结果设置全局变量true或false.
>在每个函数调用上对此全局变量的值进行分支.

我对这种方法不满意,因为它有两个缺点:

>我不确定如何自动运行cpuid并在程序开头设置一个全局变量,因为我正在分发一个.a文件并且无法控制最终二进制文件中的main函数.如果它提供了更好的解决方案,我很高兴在这里使用C,只要最终的库仍然可以与C程序链接调用.
>这会在每个函数调用上产生开销,理想情况下,唯一的开销是在程序启动时.

有没有比我上面详述的更有效的解决方案?

解决方法

x264使用init函数(在调用任何其他东西之前需要调用库的用户,或者类似的东西)来根据cpuID结果设置函数指针的结构.包括考虑到pshufb在支持它的一些早期cpu上运行缓慢.

如果你的功能依赖于pdep / pext,你可能想要检测AMD与英特尔,因为AMD的pdep / pext非常慢并且可能不值得在Ryzen上使用,即使它可用. (有关说明表,请参阅https://agner.org/optimize/.)

函数指针的开销相当低,与调用共享库或DLL中的函数大致相同.调用[rel funcptr]而不是调用func. (在编译器生成的asm中调用您的函数).

CPU dependent code: how to avoid function pointers?在C中显示一个非常简单的例子,并且正在寻找避免它的方法.通过动态链接,您可以在动态链接时进行cpu检测,因此动态链接间接也成为您的cpu调度间接(就像glibc选择优化的memcpy实现一样).

但是对于.a的静态链接,只需要将基本版本静态初始化的函数指针,以及你的cpu初始化函数(希望在任何函数指针被解除引用之前运行)重写它们以指向最佳版本.当前的cpu.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...