У меня была функция, которая выглядела так (показывая только важную часть):
double CompareShifted(const std::vector<uint16_t>& l, const std::vector<uint16_t> &curr, int shift, int shiftY) {
...
for(std::size_t i=std::max(0,-shift);i<max;i++) {
if ((curr[i] < 479) && (l[i + shift] < 479)) {
nontopOverlap++;
}
...
}
...
}
Написанный таким образом, функция заняла ~ 34 мс на моей машине. После изменения условия на умножение bool (чтобы код выглядел следующим образом:
double CompareShifted(const std::vector<uint16_t>& l, const std::vector<uint16_t> &curr, int shift, int shiftY) {
...
for(std::size_t i=std::max(0,-shift);i<max;i++) {
if ((curr[i] < 479) * (l[i + shift] < 479)) {
nontopOverlap++;
}
...
}
...
}
время выполнения уменьшилось до ~ 19 мс.
Используемый компилятор был GCC 5.4.0 с -O3 и после проверки сгенерированного кода asm с использованием godbolt.org я обнаружил, что первый пример генерирует скачок, а второй - нет. Я решил попробовать GCC 6.2.0, который также генерирует команду перехода при использовании первого примера, но GCC 7, похоже, больше не генерирует его.
Выяснение этого способа ускорения кода было довольно ужасным и заняло довольно много времени. Почему компилятор ведет себя так? Предназначено ли это для программистов? Есть ли еще что-то подобное?
EDIT: ссылка на godbolt https://godbolt.org/g/5lKPF3