Ответ 1
Боковое примечание: если у вас есть код типа
if (p) a = 20; else a = 10;
то нет никакой ветки. Компилятор использует условное перемещение (см. Почему условное перемещение не уязвимо для отказа от ветвления?)
Я пишу некоторый звуковой код, где в основном все это крошечный цикл. Ошибки прогнозирования ветвей, как я их понимаю, - это довольно большая проблема с производительностью, и я изо всех сил стараюсь сохранить свободную ветку кода. Но есть только до сих пор, что может занять меня, что заставило меня задуматься о разных видах ветвления.
В С++ условная ветвь для фиксированной цели:
int cond_fixed(bool p) {
if (p) return 10;
return 20;
}
И (если я правильно понимаю этот вопрос), безусловная ветвь переменной цели:
struct base {
virtual int foo() = 0;
};
struct a : public base {
int foo() { return 10; }
};
struct b : public base {
int foo() { return 20; }
};
int uncond_var(base* p) {
return p->foo();
}
Есть ли различия в производительности? Мне кажется, что если один из двух методов был, очевидно, быстрее, чем другой, компилятор просто преобразил бы код, чтобы он соответствовал.
В тех случаях, когда предсказание ветвлений имеет очень большое значение, , какие сведения о производительности полезны для понимания?
РЕД.. Фактическая операция x : 10 ? 20
- это просто место. Фактическая операция, следующая за ветвью, является, по крайней мере, достаточно сложной, что выполнение обоих неэффективно. Кроме того, если бы у меня было достаточно информации, чтобы разумно использовать __builtin_expect
, предсказание ветвлений было бы не проблемой в этом случае.
Боковое примечание: если у вас есть код типа
if (p) a = 20; else a = 10;
то нет никакой ветки. Компилятор использует условное перемещение (см. Почему условное перемещение не уязвимо для отказа от ветвления?)
Вы не упомянули своего компилятора. Я когда-то использовал GCC для приложения с критическими характеристиками (конкурс в моем университете фактически), и я помню, что GCC имеет макрос __builtin_expect
. Я прошел все условия в своем коде и закончил с 5-10% ускорением, что, по моему мнению, было потрясающим, учитывая тот факт, что я обратил внимание на почти все, что я знал (макет памяти и т.д.), И что я сделал "ничего не измените в отношении самого алгоритма.
Алгоритм был довольно простым поиском глубины. И я запустил его на Core 2 Duo, но не уверен, какие из них.