【发布时间】:2018-07-24 01:40:04
【问题描述】:
以下完整代码可以将fast inverse square root 的速度与 1/sqrt() 进行比较。根据维基百科中的sentence,(即该算法比用另一种方法计算平方根并通过浮点除法计算倒数快大约四倍。)
但这就是我在这里的原因:它比 1/sqrt() 慢。我的代码有问题吗?请。
#include <stdio.h>
#include <time.h>
#include <math.h>
float FastInvSqrt (float number);
int
main ()
{
float x = 1.0e+100;
int N = 100000000;
int i = 0;
clock_t start2 = clock ();
do
{
float z = 1.0 / sqrt (x);
i++;
}
while (i < N);
clock_t end2 = clock ();
double time2 = (end2 - start2) / (double) CLOCKS_PER_SEC;
printf ("1/sqrt() spends %13f sec.\n\n", time2);
i = 0;
clock_t start1 = clock ();
do
{
float y = FastInvSqrt (x);
i++;
}
while (i < N);
clock_t end1 = clock ();
double time1 = (end1 - start1) / (double) CLOCKS_PER_SEC;
printf ("FastInvSqrt() spends %f sec.\n\n", time1);
printf ("fast inverse square root is faster %f times than 1/sqrt().\n", time2/time1);
return 0;
}
float
FastInvSqrt (float x)
{
float xhalf = 0.5F * x;
int i = *(int *) &x; // store floating-point bits in integer
i = 0x5f3759df - (i >> 1); // initial guess for Newton's method
x = *(float *) &i; // convert new bits into float
x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
return x;
}
结果如下:
1/sqrt() spends 0.850000 sec.
FastInvSqrt() spends 0.960000 sec.
fast inverse square root is faster 0.885417 times than 1/sqrt().
【问题讨论】:
-
您在哪些值上测试您的功能?仅使用例如输入 1 运行代码可能会产生初始常量损失。所以也许可以尝试一些非常大的值,并在此基础上进行基准测试。
-
您的代码是垃圾,因为循环内容不使用平方根算法的结果。重新编码,以便循环每次计算不同的倒数平方根并打印出结果的总和并启用优化。此外,您的逆平方根至少需要 3 次迭代才能收敛到单精度精度,并且应该同时计算 8 次,以便编译器可以使用 ymm 寄存器对操作进行矢量化。
-
@San Tseng 维基百科声称
FastInvSqrt比特定替代方案快四倍的参考文献是十五年前发表于 2003 年的一篇论文。没有什么特别的理由可以假设 2003 年硬件平台、工具链和库的真实情况今天仍然适用,因为从那时起所有这些都发生了重大变化(例如 x86 处理器上平方根的硬件指令已变为 从那时起快得多)。 -
@DillonDavis 禁用优化的计时测试是徒劳的。测试必须计算
N不同的倒数平方根并且必须使用输出中的所有结果,否则优化器可以跳过循环。对于 O.P.,您的循环执行 100000001 次迭代,而不仅仅是 1 次。如果只计算 1 倒数平方根需要大约一秒钟,那么这将是可怜的,这不是正在发生的事情。 -
@user5713492 浮点单元作为一个整体变得更宽,但这适用于平方根和相乘。上次我检查,平方根和 add/mul/fma 之间的吞吐量比明显小于 15 年前,从 1:25 下降到 1:6(或大约)。
标签: c performance math square-root