Учитывая прогноз ветвления, а также эффект оптимизации компилятора, какой код имеет тенденцию предлагать превосходную производительность?
Обратите внимание, что bRareExceptionPresent представляет собой необычное условие. Это не нормальный путь логики.
/* MOST COMMON path must branch around IF clause */
bool SomeFunction(bool bRareExceptionPresent)
{
// abort before function
if(bRareExceptionPresent)
{
return false;
}
.. function primary body ..
return true;
}
/* MOST COMMON path does NOT branch */
bool SomeFunction(bool bRareExceptionPresent)
{
if(!bRareExceptionPresent)
{
.. function primary body ..
}
else
{
return false;
}
return true;
}
optimization
theory
dyasta
источник
источник
Ответы:
В современном мире это не имеет большого значения, если это вообще так.
Динамическое прогнозирование ветвлений (о чем думали десятилетия (см. «Анализ рабочих нагрузок системы динамического прогнозирования ветвлений», опубликованный в 1996 г.)) - довольно распространенное место.
Пример этого можно найти в процессоре ARM. Из информационного центра Arm по прогнозированию отраслей
Тогда возникает вопрос: что такое динамическое предсказание ветвления в процессоре ARM? Последовательное чтение динамического прогнозирования ветвлений показывает, что в нем используется 2-битная схема прогнозирования (описанная в статье), которая позволяет получить информацию о том, является ли ветвь сильной или слабой или нет.
Со временем (и под временем я имею в виду несколько проходов через этот блок) это накапливает информацию о том, каким образом пойдет код.
Для статического предсказания он смотрит на то, как выглядит сам код и как выполняется ветвление в тесте - на предыдущую инструкцию или на следующую в коде:
Как упоминал Спарки, это основано на понимании того, что петля чаще всего петля. Цикл ветвится в обратном направлении (у него есть ветвь в конце цикла, чтобы перезапустить его вверху) - он обычно делает это.
Опасность попытки угадать компилятор заключается в том, что вы не знаете, как этот код будет скомпилирован (и оптимизирован). И по большей части это не имеет значения. С динамическим прогнозированием, дважды через функцию он будет предсказывать пропуск через оператор защиты для преждевременного возврата. Если производительность двух очищенных конвейеров имеет критическое значение, есть и другие проблемы, о которых следует беспокоиться.
Время, которое требуется для чтения одного стиля над другим, вероятно, имеет большее значение - сделать код чистым, чтобы человек мог его прочитать, потому что компилятор будет работать нормально, независимо от того, насколько беспорядочным или идеализированным вы будете писать код.
источник
Насколько я понимаю, в первый раз, когда ЦП встречает ветвь, он будет предсказывать (если поддерживается), что прямые ветки не берутся, а обратные ветви. Основанием для этого является то, что циклы (которые обычно разветвляются в обратном направлении) предполагаются взятыми.
На некоторых процессорах вы можете дать подсказку в инструкции по сборке относительно того, какой путь наиболее вероятен. Подробности этого ускользнут от меня на данный момент.
Кроме того, некоторые компиляторы C также поддерживают статическое предсказание ветвления, так что вы можете указать компилятору, какая ветвь более вероятна. В свою очередь, он может реорганизовать сгенерированный код или использовать измененные инструкции, чтобы воспользоваться этой информацией (или даже просто игнорировать ее).
Надеюсь это поможет.
источник
__builtin_expect
?