pow(x,0.5f)的快速实现比快速sqrt(x)快吗?

时间:2012-08-04 17:43:58

标签: c++ c performance math

我想知道pow()的快速实现,例如this one,是否比快速sqrt(x)更快地获得整数的平方根。我们知道

sqrt(x) = pow(x, 0.5f)

我自己无法测试速度,因为我没有找到sqrt的快速实现。 我的问题是:pow(x,0.5f)的快速实现是否比快速sqrt(x)更快?

编辑:我的意思是powf - pow需要浮动双打。 (双打更具误导性)

3 个答案:

答案 0 :(得分:23)

关于C标准库sqrtpow,答案是

首先,如果pow(x, .5f)sqrt(x)的实施更快,则分配到维护sqrt的工程师将用[{1}}替换实现。

其次,商业库中sqrt的实现通常是专门为执行该任务而优化的,通常由那些了解编写高性能软件以及使用汇编语言编写或接近汇编语言以便从处理器获得最佳性能的人员进行优化。

第三,许多处理器具有执行sqrt或帮助计算它的指令。 (通常,有一条指令可以提供平方根倒数的估计值和一条改进该估计值的指令。)

然而

您提到的链接/问题的代码是使用粗略近似的pow(x, .5f)尝试粗略估算sqrt

我将问题中提到的pow近似例程的最终版本转换为C,并在计算pow时测量它的运行时间。我还测量了系统的运行时间(Mac OS X 10.8)pow和sqrt以及the sqrt approximation here(一次迭代并乘以最后的参数得到平方根,而不是它的倒数)。

首先,计算结果:pow近似值返回1.72101。 sqrt近似值返回1.73054。系统pow和sqrt返回的正确值是1.73205。

在MacPro4,1上以64位模式运行,pow近似需要大约6个周期,系统pow需要29个周期,平方根近似需要10个周期,系统sqrt需要29个周期。这些时间可能包括加载参数和存储结果的一些开销(我使用volatile变量强制编译器不要优化其他无用的循环迭代,以便我可以测量它们。)

(这些时间是“有效吞吐量”,实际上是从一个呼叫开始到另一个呼叫开始时的CPU周期数。)

答案 1 :(得分:2)

结果在MSVC ++ 2013 64位模式下运行以下代码,完全优化。 sqrt()的性能为~9X;

距离是2619435809228.278300

Pow()经过的时间是18413.000000毫秒

距离是2619435809228.278300

Sqrt()经过的时间是2002.000000毫秒

#define LOOP_KNT 249000000  // (SHRT_MAX * 1024)

int main(void)    {
    time_t start = clock();

    double distance = 0, result = 0;
    start = clock();
    for(int i=0; i<LOOP_KNT; i++) {
        result = pow(i, 0.50);
        distance += result;
    }
    printf("\nDistance is %f", distance);
   printf("\nPow() elapsed time was %f milliseconds", (double)clock() - (double)(start));

   distance = 0, result = 0;
   start = clock();
    for(int i=0; i<LOOP_KNT; i++) {
        result = sqrt(i);
        distance += result;
    }
    printf("\nDistance is %f", distance);
    printf("\nSqrt() elapsed time was %f milliseconds", (double)clock() - (double)(start));

   printf("\nHit any key to end program.\n");
   getchar();

   return 0;
}

不需要绞痛,理论化或教化。只需编写基准并观察结果。

答案 2 :(得分:1)

通常,在给出相同的错误限制的情况下,更具体的问题可以比更普遍的问题更优化。

因此,您可以采用该算法,并将b替换为常量0.5,现在您的sqrt()至少与pow()一样快。现在它是常量,编译器(或人)可以根据它进行优化。

请注意,pow()函数是近似值并且具有(相对)大的误差,因此不像大多数库sqrt函数那样准确。如果你将sqrt的实现放宽到相同的近似限制,那么你的确可以做到至少同样快。