Это подсказки компилятора для GCC. Они используются в условных выражениях, чтобы сообщать компилятору о вероятности перехода на ветку. Это может помочь компилятору составить код таким образом, который оптимален для наиболее частого результата.
Они используются так:
if (likely(some_condition)) {
// the compiler will try and make the code layout optimal for the case
// where some_condition is true, i.e. where this block is run
most_likely_action();
} else {
// this block is less frequently used
corner_case();
}
Его следует использовать с большой осторожностью (т.е. на основе фактических результатов профилирования веток). Неправильный намек может ухудшить производительность (очевидно).
Некоторые примеры того, как код может быть оптимизирован, легко найти с помощью поиска GCC __builtin_expect. Этот пост gcc оптимизация: __builtin_expect, например, детализирует разборку с ним.
Тип оптимизации, которая может быть сделана, очень зависит от процессора. Общая идея заключается в том, что часто процессоры будут выполнять код быстрее, если он не будет переходить / перескочить повсюду. Чем он более линейный и чем более предсказуемы ветви, тем быстрее он будет работать. (Это особенно верно для процессоров с глубокими конвейерами, например.)
Таким образом, компилятор выдаст код так, что наиболее вероятная ветвь не будет включать скачок, если, например, это то, что предпочитает целевой процессор.
Что подразумевается под единорогами ? Это технический термин или просто наполнитель?
Сен
Я убрал единорогов, чтобы избежать путаницы.
Мат
Не могли бы вы рассказать о том, как компилятор попытается сделать макет кода оптимальным для данного случая ? Я хотел бы знать, как это происходит.
Сен
добавил немного информации об этом. общего способа оптимизации кода не существует, все зависит от процессора.
Мат
2
Давайте декомпилируем, чтобы увидеть, что GCC 4.8 делает с ним
Без ожидания
#include "stdio.h"
#include "time.h"
int main() {
/* Use time to prevent it from being optimized away. */
int i = !time(NULL);
if (i)
printf("%d\n", i);
puts("a");
return 0;
}
Компилировать и декомпилировать с GCC 4.8.2 x86_64 Linux:
printf(Компилируется __printf_chk) был перенесен в самом конце функции, после того, как putsи возвращение , чтобы улучшить предсказание ветвлений , как упоминалось другими ответами.
Так что это в основном так же, как:
int i = !time(NULL);
if (i)
goto printf;
puts:
puts("a");
return 0;
printf:
printf("%d\n", i);
goto puts;
Ответы:
Это подсказки компилятора для GCC. Они используются в условных выражениях, чтобы сообщать компилятору о вероятности перехода на ветку. Это может помочь компилятору составить код таким образом, который оптимален для наиболее частого результата.
Они используются так:
Его следует использовать с большой осторожностью (т.е. на основе фактических результатов профилирования веток). Неправильный намек может ухудшить производительность (очевидно).
Некоторые примеры того, как код может быть оптимизирован, легко найти с помощью поиска
GCC __builtin_expect
. Этот пост gcc оптимизация: __builtin_expect, например, детализирует разборку с ним.Тип оптимизации, которая может быть сделана, очень зависит от процессора. Общая идея заключается в том, что часто процессоры будут выполнять код быстрее, если он не будет переходить / перескочить повсюду. Чем он более линейный и чем более предсказуемы ветви, тем быстрее он будет работать. (Это особенно верно для процессоров с глубокими конвейерами, например.)
Таким образом, компилятор выдаст код так, что наиболее вероятная ветвь не будет включать скачок, если, например, это то, что предпочитает целевой процессор.
источник
Давайте декомпилируем, чтобы увидеть, что GCC 4.8 делает с ним
Без ожидания
Компилировать и декомпилировать с GCC 4.8.2 x86_64 Linux:
Вывод:
Порядок инструкций в памяти не изменился: сначала и,
printf
а затемputs
иretq
возврат.С ожиданием
Теперь замените
if (i)
на:и мы получаем:
printf
(Компилируется__printf_chk
) был перенесен в самом конце функции, после того, какputs
и возвращение , чтобы улучшить предсказание ветвлений , как упоминалось другими ответами.Так что это в основном так же, как:
Эта оптимизация не была сделана с
-O0
.Но удачи в написании примера, который работает быстрее,
__builtin_expect
чем без, в те дни процессоры действительно умны . Мои наивные попытки здесь .С ++ 20
[[likely]]
и[[unlikely]]
C ++ 20 стандартизировал эти встроенные модули C ++: /programming/51797959/how-to-use-c20s-likely-unlikely-attribute-in-if-else-statement Они, скорее всего, каламбур!) сделать то же самое.
источник