C中的整数幂

jmd*_*_dk 6 c optimization gcc gnu compiler-optimization

在C代码中,通常写

a = b*b;
Run Code Online (Sandbox Code Playgroud)

代替

a = pow(b, 2.0);
Run Code Online (Sandbox Code Playgroud)

对于double变量.我知道因为它pow是一个能够处理非整数指数的通用函数,所以应该天真地认为第一个版本更快.我不知道编译器(gcc)是否将调用转换为pow整数指数,以指示乘法作为任何可选优化的一部分.

假设没有进行这种优化,那么手动写出乘法的最大整数指数是b*b* ... *b多少,如?

我知道我可以在给定的机器上进行性能测试,以确定我是否应该关心,但我想更深入地了解什么是"正确的事情".

tec*_*rus 2

您想要的是-ffinite-math-only -ffast-math并且可能#include <tgmath.h>-Ofast这与不强制优化相同-O3

它不仅在-ffinite-math-only and -ffast-math启用时有助于此类优化,而且当您忘记将正确的后缀附加到(非双精度)数学函数时,类型通用数学还可以帮助进行补偿。

例如:

#include <tgmath.h>
float pow4(float f){return pow(f,4.0f);}
//compiles to
pow4:
    vmulss  xmm0, xmm0, xmm0
    vmulss  xmm0, xmm0, xmm0
    ret
Run Code Online (Sandbox Code Playgroud)

对于 clang 来说,这适用于高达 32 的幂,而 gcc 则适用于至少 2,147,483,647 的幂(据我检查),除非-Os启用(因为 a jmpto the pow 函数在技术上更小) - 使用 -Os,它将只做2的幂。

警告-ffast-math只是其他几种优化的方便别名,其中许多优化违反了各种标准。如果您只想使用最少的标志来获得所需的行为,那么您可以使用-fno-math-errno -funsafe-math-optimizations -ffinite-math-only