如果您处于乘法速度很快的体系结构中,C 中是否有任何方法可以在编译时检查?

Is there any way in C to check at compile time if you are on an architecture where multiplication is fast?

有什么方法可以让 C 代码判断它是否在乘法速度很快的体系结构上编译?是否有一些宏 __FAST_MULT__ 或在这些架构上定义的东西?

例如,假设您正在实现一个函数,通过移位加法*确定 64 位整数的汉明权重。有two optimal algorithms for that:一个需要17次算术运算,而另一个只需要12次,但其中有一次是乘法运算。因此,第二个算法快 30%,if 你在硬件上 运行 乘法与加法花费相同的时间 - 但在乘法的系统上慢得多被实现为重复加法。
因此,在编写这样的函数时,能够在编译时检查是否是这种情况,并在适当的情况下在两种算法之间切换是很有用的:

unsigned int popcount_64(uint64_t x) {
    x -= (x >> 1) & 0x5555555555555555;                             // put count of each 2 bits into those 2 bits
    x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); // put count of each 4 bits into those 4 bits
    x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;                        // put count of each 8 bits into those 8 bits
#ifdef __FAST_MULT__
    return (x * 0x0101010101010101)>>56;                            // returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
#else // __FAST_MULT__
    x += x >>  8;                                                   // put count of each 16 bits into their lowest 8 bits
    x += x >> 16;                                                   // put count of each 32 bits into their lowest 8 bits
    x += x >> 32;                                                   // put count of each 64 bits into their lowest 8 bits
    return x & 0x7f;
#endif // __FAST_MULT__
}

有什么办法吗?

* 是的,我知道 __builtin_popcount() 函数;这只是一个例子。

Is there any way for C code to tell whether it is being compiled on an architecture where multiplication is fast? Is there some macro __FAST_MULT__ or something which is defined on those architectures?

不,标准 C 不提供任何此类功能。特定的编译器可能会提供扩展之类的东西,但我并没有特别意识到实际上有什么。

这类事情可以在构建配置期间进行测试,例如通过 Autoconf 或 CMake,在这种情况下,您可以在适当的地方自己提供符号。

或者,一些 C 编译器确实提供了宏来指示编译代码所针对的体系结构。您可以将其与各种机器体系结构的细节知识结合使用,以在两种算法之间进行选择——毕竟,这就是此类宏的目的。

或者您可以依靠构建程序的人来选择,通过配置选项,通过定义宏或其他方式。

我认为没有专门针对快速乘法功能的预定义宏。

然而,有很多predefined compiler macros for different architectures所以如果你事先知道什么架构或CPU支持快速乘法指令,你可以使用那些宏请定义您自己的特定应用程序,表示快速乘法。

例如:

#if (defined __GNUC__ && defined __arm__ && defined __ARM_ARCH_'7'__) ||
    (defined __CC_ARM && (__TARGET_ARCH_ARM == 7))
#define FAST_MULT
#endif