Часто известные как likely
и unlikely
макросы помогают компилятору узнать, будет ли if
он вводиться или пропускается. Его использование приводит к некоторым (довольно незначительным) улучшениям производительности.
Я начал использовать их недавно, и я не уверен, как часто следует использовать такие подсказки. В настоящее время я использую его с проверкой ошибок if
s, которые обычно помечаются как unlikely
. Например:
mem = malloc(size);
if (unlikely(mem == NULL))
goto exit_no_mem;
Вроде бы все нормально, но проверка ошибок if
происходит довольно часто и, следовательно, использование упомянутых макросов.
У меня вопрос, слишком ли много likely
и unlikely
макросов при каждой проверке ошибок if
?
В то время как мы в этом, какие другие места они часто используют?
В моем текущем использовании это библиотека, которая абстрагируется от подсистемы реального времени, поэтому программы становятся переносимыми между RTAI, QNX и другими. Тем не менее, большинство функций довольно маленькие и напрямую вызывают одну или две другие функции. Многие даже static inline
функции.
Итак, во-первых, это не приложение, которое я мог бы профилировать. Не имеет смысла «определять узкие места», поскольку это библиотека, а не отдельное приложение.
Во-вторых, это что-то вроде: «Я знаю, что это маловероятно, я мог бы также рассказать об этом компилятору». Я не пытаюсь активно оптимизировать if
.
источник
likely
иunlikely
существует и что они делают. Я не нашел ничего, что могло бы предложить, когда и где лучше всего их использовать.Ответы:
Вам нужна производительность настолько сильно, что вы готовы загрязнить свой код этим? Это небольшая оптимизация.
Если вы не можете ответить
yes
на все вышеизложенное, не беспокойтесь о подобных вещах.Редактировать: в ответ на редактирование. Даже если вы не можете профилировать, вы можете оценить горячие точки. Функция распределения памяти, которая вызывается всеми, является хорошим кандидатом, тем более что для работы всей библиотеки требуется только одно использование макроса.
источник
(un)likely
макрос используется редко и только в чрезвычайно критичном для производительности коде? Является ли «плохой практикой» его частое использование или просто «ненужное»?if (likely(x==2 || x==3)) doOneThing(); else switch(x) { ... }
, может судить, что использование программистомif
значений 2 и 3 было не просто следствием того, что программист не знал, что C может связывать двеcase
метки с одним обработчиком.Если вы пишете для x86 / x64 (и не используете 20-летние процессоры), выигрыш в производительности от использования __builtin_expect () будет незначительным, если таковой имеется. Причина этого в том, что современные процессоры x86 / x64 (хотя на 100% не уверены в Atom) имеют динамическое предсказание ветвления, поэтому, по сути, ЦП «узнает» о ветвлении, которое используется чаще. Конечно, эта информация может храниться только для ограниченного числа филиалов, однако возможны только два случая. Если (а) это «часто используемая» ветвь, то ваша программа получит выгоду от этого динамического предсказания ветвления, а если (б) это «редкая» ветвь, вы не увидите реального снижения производительности из-за неправильных предсказаний в такие редкие ветки (20 циклов ошибочного предсказания ветвления процессора не слишком плохи, если это происходит однажды в синей луне).
NB: это НЕ означает, что на современных x86 / x64 важность ошибочного прогнозирования ветвлений стала ниже: любая ветвь с вероятностью скачка-сдвига 50-50 все равно будет подвергаться штрафу (циклы ЦПИ II-20), поэтому во внутренних ветвях цикла могут все еще нужно избегать. Это только важность __builtin_expect () на x86 / x64, которая уменьшилась (IIRC, около 10-15 лет назад или около того) - в основном из-за динамического предсказания ветвлений.
NB2: для других платформ, кроме x86 / x64, YMMV.
источник
unlikely
-notation.