При попытке сравнить некоторые параметры моего кода (используя 128-битные целые числа или нет) я наблюдал поведение, которое я просто не могу понять. Может ли кто-нибудь пролить свет на это?
#include <stdio.h>
#include <stdint.h>
#include <time.h>
int main(int a, char** b)
{
printf("Running tests\n");
clock_t start = clock();
unsigned __int128 t = 13;
for(unsigned long i = 0; i < (1UL<<30); i++)
t += 23442*t + 25;
if(t == 0) printf("0\n");
printf("u128, +25, took %fs\n", double(clock() - start)/CLOCKS_PER_SEC);
start = clock();
t = 13;
for(unsigned long i = 0; i < (1UL<<30); i++)
t += 23442*t;
if(t == 0) printf("0\n");
printf("u128, no+, took %fs\n", double(clock() - start)/CLOCKS_PER_SEC);
start = clock();
unsigned long u = 13;
for(unsigned long i = 0; i < (1UL<<30); i++)
u += 23442*u + 25;
if(u == 0) printf("0\n");
printf("u64 , +25, took %fs\n", double(clock() - start)/CLOCKS_PER_SEC);
start = clock();
u = 13;
for(unsigned long i = 0; i < (1UL<<30); i++)
u += 23442*u;
if(u == 0) printf("0\n");
printf("u64 , no+, took %fs\n", double(clock() - start)/CLOCKS_PER_SEC);
return 0;
}
(Обратите внимание, что printf здесь, так что gcc не оптимизирует цикл for) В моей системе это надежно производит следующий вывод:
u128, +25, took 2.411922s
u128, no+, took 1.799805s
u64 , +25, took 1.797960s
u64 , no+, took 2.454104s
В то время как 128-битное целочисленное поведение имеет смысл, я не вижу, как бит 64-разрядного цикла с меньшим количеством операций выполняет значительно (30%) медленнее.
Это известное поведение? Каково было бы общее правило, пытаясь извлечь выгоду из этой оптимизации при написании таких циклов?
Изменить: поведение наблюдается только при компиляции с опцией -O3.
gcc -lstdc++ -O3 -o a main.cpp
u128, +25, took 2.413949s
u128, no+, took 1.799469s
u64 , +25, took 1.798278s
u64 , no+, took 2.453414s
gcc -lstdc++ -O2 -o a main.cpp
u128, +25, took 2.415244s
u128, no+, took 1.800499s
u64 , +25, took 1.798699s
u64 , no+, took 1.348133s