分裂的速度更快?双打/浮点数/ UInt32/UInt64?在C++/C中

2 c++ floating-point double performance 32bit-64bit

我做了一些速度测试,以确定在进行数字乘法或除法时最快的速度.我必须努力工作以击败优化者.我得到了无意义的结果,例如在2微秒内运行的大量循环,或者乘法与除法的速度相同(如果只是那样).

在我最终努力工作以击败足够的编译器优化之后,同时仍然让它优化速度,我得到了这些速度结果.他们可能对别人感兴趣?

如果我的测试仍然悬而未决,请告诉我,但要善待,因为我只花了两个小时写这个垃圾:P

64 time: 3826718 us
32 time: 2476484 us
D(mul) time: 936524 us
D(div) time: 3614857 us
S time: 1506020 us
Run Code Online (Sandbox Code Playgroud)

使用双打"乘以除法"似乎是进行除法的最快方法,其次是整数除法.我没有测试分裂的准确性.可能是"正确的划分"更准确吗?我不想在这些速度测试结果之后发现,因为我只是在基数为10的常数上使用整数除法,让我的编译器为我优化它;)(并且不会破坏它的优化).

这是我用来获得结果的代码:

#include <iostream>

int Run(int bla, int div, int add, int minus) {
    // these parameters are to force the compiler to not be able to optimise away the
    // multiplications and divides :)
    long LoopMax = 100000000;

    uint32_t Origbla32 = 1000000000;
    long i = 0;

    uint32_t bla32 = Origbla32;
    uint32_t div32 = div;
    clock_t Time32 = clock();
    for (i = 0; i < LoopMax; i++) {
        div32 += add;
        div32 -= minus;
        bla32 = bla32 / div32;
        bla32 += bla;
        bla32 = bla32 * div32;
    }
    Time32 = clock() - Time32;

    uint64_t bla64 = bla32;
    clock_t Time64 = clock();
    uint64_t div64 = div;
    for (long i = 0; i < LoopMax; i++) {
        div64 += add;
        div64 -= minus;
        bla64 = bla64 / div64;
        bla64 += bla;
        bla64 = bla64 * div64;
    }
    Time64 = clock() - Time64;

    double blaDMul = Origbla32;
    double multodiv = 1.0 / (double)div;
    double multomul = div;
    clock_t TimeDMul = clock();
    for (i = 0; i < LoopMax; i++) {
        multodiv += add;
        multomul -= minus;
        blaDMul = blaDMul * multodiv;
        blaDMul += bla;
        blaDMul = blaDMul * multomul;
    }
    TimeDMul = clock() - TimeDMul;

    double blaDDiv = Origbla32;
    clock_t TimeDDiv = clock();
    for (i = 0; i < LoopMax; i++) {
        multodiv += add;
        multomul -= minus;
        blaDDiv = blaDDiv / multomul;
        blaDDiv += bla;
        blaDDiv = blaDDiv / multodiv;
    }
    TimeDDiv = clock() - TimeDDiv;

    float blaS = Origbla32;
    float divS = div;
    clock_t TimeS = clock();
    for (i = 0; i < LoopMax; i++) {
        divS += add;
        divS -= minus;
        blaS = blaS / divS;
        blaS += bla;
        blaS = blaS * divS;
    }
    TimeS = clock() - TimeS;

    printf("64 time: %i us  (%i)\n", (int)Time64, (int)bla64);
    printf("32 time: %i us  (%i)\n", (int)Time32, bla32);

    printf("D(mul) time: %i us  (%f)\n", (int)TimeDMul, blaDMul);
    printf("D(div) time: %i us  (%f)\n", (int)TimeDDiv, blaDDiv);
    printf("S time: %i us  (%f)\n", (int)TimeS, blaS);

    return 0;
}

int main(int argc, char* const argv[]) {
    Run(0, 10, 0, 0); // adds and minuses 0 so it doesn't affect the math, only kills the opts
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Joe*_*erg 9

有很多方法可以执行某些算术,因此可能没有一个答案(移位,小数乘法,实际除法,通过对数单位的某些往返等等;这些可能都有不同的相对成本,具体取决于操作数和资源分配).

让编译器使用它具有的程序和数据流信息来完成它的工作.

对于适用于x86上的汇编的一些数据,您可能会看到:"AMD和Intel x86处理器的指令延迟和吞吐量"

  • "击败"优化器是为了防止死码消除,因为我们对优化器旨在避免的副作用感兴趣:时间.同样的事情可能发生在更简单的情况下,试图看看这个循环的运行速度有多快:`for(int i = 1; i <= 1000000; ++ i){}`.就语言而言,允许优化器完全消除该循环. (3认同)