Если мы игнорируем SMT (например, гиперпоточность), большинство архитектур имеют предсказатель ветвления для каждого аппаратного потока. Он тесно связан с блоком выборки отдельного ядра. Некоторые (AMD?) хранят некоторую информацию о предсказании переходов в I-кэше L1/L2, но в основном нацелены на следующую выборку.
Поэтому, если вы не запускаете свой код на SMT, вы находитесь в раю и каждый раз будете получать 100% предсказание за счет нескольких инструкций.
Если вы запустите свой код на SMT, вы часто обнаружите, что ваша жизнь превратилась в ад, с более чем 50% неправильных прогнозов.
Теперь вы можете легко решить свою проблему, вам просто нужно использовать больше кода, проверить свое условие раньше и вызвать ветку вашего кода с do_something или do_else в ней.
Если у вас есть цикл, который вызывает вашу функцию, где у вас есть ветка, вы можете сделать что-то вроде:
если (что-то) do_something_loop(); иначе do_else_loop();
void do_something_loop() { for (auto x: myVec) do_something; }
Недостатком этого является то, что вам нужно поддерживать 2 почти равные ветви кода.
Или вы можете иметь свою ветку в вызове функции branch_me(), которую вы можете сделать функцией шаблона, и из-за магии устранения мертвого кода вы не должны получать никаких ветвей в циклах.
Код концепции С++.
template<bool b_something>
void brancher() {
// do things
if (b_something)
// do_something
else
// do_else
}
// do more things
}
void branch_user() {
if (something) {
for (auto x : myVec)
brancher<true>();
} else {
for (auto x : myVec)
brancher<false>();
}
}
Теперь вам нужно только поддерживать 2 ветки внешней функции, что, надеюсь, требует меньше работы.
person
Surt
schedule
08.11.2016