Sam*_*mar 7 c c++ assembly static-libraries static-linking
我正在开发一个C库,它编译/链接到一个.a文件,用户可以静态链接到他们的代码.库的性能非常重要,因此我在x86-64汇编中编写性能关键的例程来优化性能.
对于某些例程,如果使用BMI2指令,我可以获得明显更好的性能,而不是坚持使用"标准"x86-64指令集.麻烦的是,BMI2最近刚推出,我的一些用户使用不支持这些指令的处理器.
所以,我写了两次优化例程,一次使用BMI2指令,一次不使用它们.在我目前的设置中,我将分发该.a文件的两个版本:一个需要支持BMI2指令的"快速" 版本,以及一个不需要支持BMI2指令的"慢"版本.
我问是否有办法通过分发单个.a文件来简化这一过程,该文件将根据最终应用程序运行的CPU是否支持BMI2指令动态选择正确的实现.
与StackOverflow上的类似问题不同,这里有两个特点:
if语句也可能很重要.我到目前为止提出的最快解决方案是执行以下操作:
cpuid指令检查CPU是否支持BMI2 指令.true或false取决于结果.我对这种方法不满意,因为它有两个缺点:
cpuid并设置一个全局变量,因为我正在分发一个.a文件并且无法控制main最终二进制文件中的函数.如果它提供了更好的解决方案,我很高兴在这里使用C++,只要最终的库仍然可以与C程序链接和调用.有没有比我上面详述的更有效的解决方案?
x264 使用 init 函数(库的用户需要在调用其他任何东西或类似的东西之前调用该函数)来根据 CPUID 结果设置函数指针结构。包括考虑到pshufb在一些支持它的早期 CPU 上速度很慢。
如果您的函数依赖于pdep/ pext,您可能想要检测 AMD 与 Intel 的对比,因为 AMD 的pdep/pext非常慢,并且可能不值得在 Ryzen 上使用,即使它可用。(有关说明表,请参阅https://agner.org/optimize/ 。)
函数指针的开销相当低,与调用共享库或 DLL 中的函数大致相同。  call [rel funcptr]代替call func。(在编译器生成的调用您的函数的汇编中)。
CPU 相关代码:如何避免函数指针?用 C 语言展示了一个非常简单的例子,并寻求避免它的方法。通过动态链接,您可以在动态链接时进行 CPU 检测,以便动态链接间接也成为您的 CPU 调度间接(就像 glibc 用于选择优化实现一样memcpy)。
但是对于 a 的静态链接.a,只需将函数指针静态初始化为基线版本,并且您的 CPU init 函数(希望在任何函数指针被取消引用之前运行)重写它们以指向当前 CPU 的最佳版本。