Mam taką funkcję:
uint64_t funct()
{
if(x >> 63)
{
x = x * a + b;
}
else
{
x = (x >> 1) * c + d;
}
return x;
x,a,b,c,d to liczby 64-bitowe. x jest liczbą pseudo-losową (generowaną za pomocą generatora PRNG), a zatem nie jesteśmy w stanie przewidzieć jej ostatniego bitu obliczanego w warunku x >> 63.
Czy to da się zaprogramować szybciej? Próbowałem kilku najprostszych rozwiązań, np. zapisania tego tak:
x = ((x >> 63) * (x * key[0] + key[1])) + ((1^(x >> 63)) * ((x >> 1) * key[2] + key[3]));
Próbowałem też usunąć else. Wszystko to działa nawet wolniej niż proste if/else. Czytałem trochę o branching i powoli tracę nadzieję, że da się to przyspieszyć. Jeżeli w warunku znajdzie się z np. k & 1, gdzie k zmienia się od 0 do 3: 0,1,2,3,0,1,2,3,... to kod przyspiesza znacząco. A zatem samo mnożenie z dodawaniem zajmuje tylko połowę tego co instrukcja if/else - tak kosztowna jest ona w tym przypadku.
Ponoć takie problemy można przyspieszyć w ramach mikro-optymalizacji, ale jak dokładnie się to robi? To jest wąskie gardło programu i ta funkcja jest wykonywana bez przerwy, jeżeli jej nie przyspieszę, to niewiele jest do optymalizacji w reszcie kodu.