使用新的CPU指令支持构建向后兼容的二进制文件

问题描述 投票:2回答:1

实现同一功能的多个版本的最佳方法是使用特定的CPU指令(如果在运行时进行了测试,或者如果没有,则回退到较慢的实现?

例如,x86 BMI2提供了非常有用的PDEP指令。我将如何编写C代码,以便在启动时测试正在执行的CPU的BMI2可用性,并使用两种实现方式之一-一种使用_pdep_u64调用(可用于-mbmi2),另一种使用位操作“手工”使用C代码。是否有针对此类情况的内置支持?在提供对较新的内在函数的访问权限时,我将如何使GCC为较旧的arch编译?我怀疑如果通过全局函数指针而不是每次if / else调用函数,执行速度会更快?

c gcc x86 compiler-optimization inline-assembly
1个回答
2
投票

Intel的ICC已有automatic function dispatching来为每种体系结构选择优化版本。我不知道细节,但显然它仅适用于Intel CPU,应该是unfair to other manufacturersDr. Agner Fog's blog]中有许多补丁和解决方法

[后来在Function Multiversioning中引入了称为GCC 4.8的功能。它将targettarget_clones属性添加到函数,并同时编译为函数的多个版本。然后,ClangICC采用了语法。在运行时,将自动确定当前体系结构以分发有效版本。这是Intel's Clear Linux runs so fast的原因之一。 ICC也可以在自动矢量化过程中创建multiple versions of a single loop

inline int popcount64_builtin_multiarch_loop(uint64_t data) {
    return __builtin_popcountll(data);
}

__attribute__((target_clones("popcnt","default")))
int runPopcount64_builtin_multiarch_loop(const uint8_t* bitfield, int64_t size, int repeat) {
    int res = 0;
    const uint64_t* data = (const uint64_t*)bitfield;

    for (int r=0; r<repeat; r++)
    for (int i=0; i<size/8; i++) {
        res += popcount64_builtin_multiarch_loop(data[i]);
    }

    return res;
}

请注意,PDEP and PEXT are very slow on current AMD CPUs仅应在Intel上启用它们

© www.soinside.com 2019 - 2024. All rights reserved.