我为两种不同的体系结构编译了相当大的功能:
__attribute__ ((target ("arch=broadwell"))) void doStuff()
{
doStuffImpl()
}
__attribute__ ((target ("arch=nocona"))) void doStuff()
{
doStuffImpl();
}
__attribute__((always_inline)) void doStuffImpl()
{
(...)
}
我知道这是做多版本的旧方法,但是我使用的是gcc 4.9.3。同样,doStuffImpl()实际上不是单个函数,而是内联函数,其中doStuff()是最后一个实际的函数调用,但是我认为它不会改变任何东西。
函数包含一些由编译器自动向量化的代码,但我还需要在其中添加一些手工制作的内在函数。两种口味明显不同。 问题是:如何在编译时识别哪些SIMD扩展可用? 我正在尝试类似的东西:
#ifdef __AVX2__
AVX_intrinsics();
#elif defined __SSE4.2__
SSE_intrinsics();
#endif
但似乎定义来自“全局” -march标志,而不是来自多版本覆盖的标志。
Godbolt (intrinsics are garbage, but shows my point)
我可以提取这部分并做单独的多版本化函数,但这会增加分派和函数调用的成本。 有什么办法可以编译两个函数的多版本变体的时间区分?