Я провел тестирование скорости, чтобы выяснить, что является самым быстрым при умножении или делении на числа. Мне пришлось действительно много работать, чтобы победить оптимизатора. Я получил бессмысленные результаты, такие как массивный цикл, работающий за 2 микросекунды, или то, что умножение было такой же скоростью, как деление (если бы только это было правдой).
После того, как я наконец-то достаточно усердно поработал, чтобы победить достаточное количество оптимизаций компилятора, и, тем не менее, позволив оптимизировать его по скорости, я получил эти результаты по скорости. Они могут быть интересны кому-то еще?
Если мой тест по-прежнему бесполезен, дайте мне знать, но будьте добры, увидев, как я потратил два часа на написание этого дерьма: P
64 time: 3826718 us
32 time: 2476484 us
D(mul) time: 936524 us
D(div) time: 3614857 us
S time: 1506020 us
«Умножение на деление» с использованием двойных представляется самым быстрым способом деления с последующим целочисленным делением. Я не проверял точность деления. Может ли быть так, что «правильное деление» является более точным? У меня нет желания выяснять результаты этих тестов на скорость, так как я просто буду использовать целочисленное деление на константе с основанием 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;
}