基准math.h平方根和Quake平方根

3 c++ g++

好吧,所以我登上了盘子,想知道math.h平方根与其中有神奇数字的那个相比有多快(由Quake着名但由SGI制作).

但这最终导致了对我的伤害.

我首先在Mac上尝试过这种方法,其中math.h每次都会在Windows上获胜,而魔术数字总是赢得,但我认为这完全取决于我自己的高通.

  1. 在程序运行时使用"g ++ -o sq_root sq_root_test.cpp"在Mac上进行编译,大约需要15秒才能完成.但是在发布时在VS2005中进行编译只需要一瞬间.(实际上我必须在debug中编译才能让它显示一些数字)

  2. 我的穷人的基准?这真的很蠢吗?因为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;   
}
Run Code Online (Sandbox Code Playgroud)

jal*_*alf 5

您的基准测试有几个问题.首先,您的基准测试包括从int到float的潜在昂贵的转换.如果您想知道平方根的成本,则应该对平方根进行基准测试,而不是数据类型转换.

其次,你的整个基准可以()由编译器优化掉了,因为它没有可观察到的副作用.您不使用返回的值(或将其存储在易失性存储器位置),因此编译器会发现它可以跳过整个事情.

这里的一个线索是你必须禁用优化.这意味着您的基准测试代码已被破坏.从来没有基准时禁用优化.您想知道哪个版本运行速度最快,因此您应该在实际使用的条件下对其进行测试.如果您在性能敏感的代码中使用平方根,那么您将启用优化,因此在没有优化的情况下它的行为方式完全无关紧要.

此外,您不是计算平方根计算成本的基准,而是平方根的倒数.如果你想知道哪个方法计算平方根是最快的,你必须将该1.0/...分区移动到Quake版本.(因为除法是一项非常昂贵的操作,这可能会对你的结果产生很大的影响)

最后,值得指出的是,Carmacks的小技巧被设计为在12岁的计算机上快速运行.一旦你修复了你的基准测试,你可能会发现它不再是一个优化,因为今天的CPU在计算"真正的"平方根时要快得多.