好的,所以我登上了,并且想知道math.h平方根与其中有神奇数字的那个相比有多快(由Quake着名但由SGI制作)。
但这最终导致了我受伤的世界。
我首先在Mac上尝试过这种方法,其中math.h每次都会在Windows上获胜,而魔术数字总是赢得,但我认为这完全归功于我自己的高通。
在程序运行时使用“g ++ -o sq_root sq_root_test.cpp”在Mac上进行编译,大约需要15秒才能完成。但是在发布时在VS2005中进行编译只需要一瞬间。 (实际上我必须在调试中编译才能让它显示一些数字)
我的穷人的基准?这真的很蠢吗?因为math.h得0.01,魔术数得0。 (它不能那么快吗?)
我不知道这是否重要,但Mac是Intel,PC是AMD。 Mac是否使用math.h sqroot的硬件?
我从http://en.wikipedia.org/wiki/Fast_inverse_square_root
获得了快速平方根算法//sq_root_test.cpp
#include <iostream>
#include <math.h>
#include <ctime>
float invSqrt(float x)
{
union {
float f;
int i;
} tmp;
tmp.f = x;
tmp.i = 0x5f3759df - (tmp.i >> 1);
float y = tmp.f;
return y * (1.5f - 0.5f * x * y * y);
}
int main() {
std::clock_t start;// = std::clock();
std::clock_t end;
float rootMe;
int iterations = 999999999;
// ---
rootMe = 2.0f;
start = std::clock();
std::cout << "Math.h SqRoot: ";
for (int m = 0; m < iterations; m++) {
(float)(1.0/sqrt(rootMe));
rootMe++;
}
end = std::clock();
std::cout << (difftime(end, start)) << std::endl;
// ---
std::cout << "Quake SqRoot: ";
rootMe = 2.0f;
start = std::clock();
for (int q = 0; q < iterations; q++) {
invSqrt(rootMe);
rootMe++;
}
end = std::clock();
std::cout << (difftime(end, start)) << std::endl;
}
答案 0 :(得分:5)
您的基准测试存在一些问题。首先,您的基准测试包括从int到float的潜在昂贵的转换。如果您想知道平方根的成本,则应该对平方根进行基准测试,而不是数据类型转换。
其次,您的整个基准测试可以由编译器优化(并且 ),因为它没有可观察到的副作用。您不使用返回的值(或将其存储在易失性存储器位置),因此编译器会看到它可以跳过整个事情。
这里的一个线索是你必须禁用优化。这意味着您的基准测试代码已被破坏。从不永远在基准测试时禁用优化。您想知道哪个版本运行速度最快,因此您应该在实际使用的条件下对其进行测试。如果您在性能敏感的代码中使用平方根,那么您将启用优化,因此在没有优化的情况下的行为方式完全无关紧要。
此外,您不是计算平方根计算成本的基准,而是逆平方根的成本。
如果您想知道平方根的计算方式最快,则必须将1.0/...
除法移至Quake版本。 (因为除法是一项非常昂贵的操作,这可能会对你的结果产生很大影响)
最后,值得指出的是,Carmacks的小技巧被设计为在12岁的计算机上快速运行。一旦你修复了你的基准测试,你可能会发现它不再是一个优化,因为今天的CPU在计算“真正的”平方根时要快得多。