Вероятный/маловероятный эквивалент для MSVC
Компилятор GCC поддерживает оператор __builtin_expect, который используется для определения вероятных и маловероятных макросов.
например.
#define likely(expr) (__builtin_expect(!!(expr), 1))
#define unlikely(expr) (__builtin_expect(!!(expr), 0))
Есть ли эквивалентное утверждение для компилятора Microsoft Visual C или что-то подобное?
Ответы
Ответ 1
Я говорю просто пунт
Там нет ничего подобного. Существует __assume(), но не используйте ее, это директива оптимизатора другого рода.
Действительно, встроенная в макрос встроенная в gnu причина заключается в том, что вы можете просто избавиться от него автоматически, если __GNUC__
не определен. В этих макросах нет ничего необходимого, и я уверен, что вы не заметите разницу во времени выполнения.
Резюме
Просто избавьтесь от (null out) *likely
в не-GNU. Вы не пропустите это.
Ответ 2
В соответствии с http://www.akkadia.org/drepper/cpumemory.pdf (стр. 57), все же имеет смысл использовать предсказание статической ветки, даже если процессор прогнозирует корректно динамически.
Причина этого в том, что кеш L1i будет использоваться еще эффективнее, если статическое предсказание будет выполнено правильно.
Ответ 3
Стандарт С++ 20 будет включать в себя атрибуты прогнозирования ветвлений [[likely]]
и [[unlikely]]
.
Самую последнюю версию предложения по атрибутам можно найти в http://wg21.link/p0479
Исходное предложение атрибута можно найти в http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0479r0.html
Программисты должны предпочесть PGO. Атрибуты могут легко снизить производительность, если они применяются неправильно или позже становятся неправильными при изменении программы.
Ответ 4
__ предположить должен быть схожим.
Однако, если вы хотите сделать это очень хорошо, вы должны использовать Profile Guided Optimization, а не статические подсказки.
Ответ 5
В соответствии с Документ Intel:
Чтобы эффективно писать свой код, чтобы воспользоваться этими правила, при написании инструкций if-else или switch, проверьте наиболее общие случаи сначала и работать постепенно вниз до наименее общего.
К сожалению, вы не можете написать что-то вроде
#define if_unlikely(cond) if (!(cond)); else
поскольку оптимизатор MSVC по сравнению с VS10 игнорирует такой "намек".
Поскольку я предпочитаю сначала обрабатывать ошибки в моем коде, я, кажется, пишу менее эффективный код.
К счастью, во второй раз процессор встречает ветку, он будет использовать свою статистику вместо статического намека.
Ответ 6
Я знаю, что этот вопрос касается Visual Studio, но я постараюсь ответить на максимально возможное количество компиляторов (включая Visual Studio)…
Десять лет спустя налицо прогресс! Начиная с Visual Studio 2019 MSVC до сих пор не поддерживает ничего подобного (хотя это самый популярный встроенный/встроенный), но, как упоминалось выше у Паули Ниеминена C++ 20, есть likely
/unlikely
атрибуты, которые можно использовать для создания вероятных/маловероятных макросов, а MSVC обычно довольно быстро добавляет поддержку новых стандартов C++ (в отличие от C), поэтому я ожидаю, что Visual Studio 2021 их поддержит.
В настоящее время (2019-10-14) только GCC поддерживает эти атрибуты и даже тогда применяется только к меткам, но этого достаточно, чтобы хотя бы выполнить некоторое базовое тестирование. Вот быстрая реализация, которую вы можете протестировать в Compiler Explorer:
#define LIKELY(expr) \
( \
([](bool value){ \
switch (value) { \
[[likely]] case true: \
return true; \
[[unlikely]] case false: \
return false; \
} \
}) \
(expr))
#define UNLIKELY(expr) \
( \
([](bool value){ \
switch (value) { \
[[unlikely]] case true: \
return true; \
[[likely]] case false: \
return false; \
} \
}) \
(expr))
Вы, вероятно, захотите использовать #ifdef для поддержки компиляторов, которые не могут его обработать, но, к счастью, большинство компиляторов поддерживают __builtin_expect
:
- GCC 3.0
- лязг
- ICC, так как по крайней мере 13, вероятно, гораздо дольше.
- Oracle Development Studio 12. 6+, но только в режиме C++.
- ARM 4.1
- IBM XL C/C++, поскольку, по крайней мере, 10,1, вероятно, дольше.
- TI с 6.1
- TinyCC с 0.9.27
GCC 9+ также поддерживает __builtin_expect_with_probability
. Он недоступен где-то еще, но, надеюсь, однажды... Потребуется немало догадок, пытаясь выяснить, использовать ли подобное/маловероятно или нет - вы просто устанавливаете вероятность, и компилятор (теоретически) делает правильные вещи.
Кроме того, clang поддерживает __builtin_unpredictable
(начиная с версии 3.8, но проверьте его с помощью __has_builtin(__builtin_unpredictable)
). Поскольку в наши дни многие компиляторы основаны на clang, они, вероятно, работают и в них.
Если вы хотите, чтобы все было закончено и готово к работе, вас может заинтересовать один из моих проектов, Хедли. Это единственный общедоступный заголовок C/C++, который работает практически на всех компиляторах и содержит множество полезных макросов, включая HEDLEY_LIKELY
, HEDLEY_UNLIKELY
, HEDLEY_UNPREDICTABLE
, HEDLEY_PREDICT
, HEDLEY_PREDICT_TRUE
и HEDLEY_PREDICT_FALSE
. У него еще нет версии C++ 20, но она скоро должна появиться…
Даже если вы не хотите использовать Хедли в своем проекте, вы можете проверить реализации там, а не полагаться на списки выше; Я, вероятно, забуду обновить этот ответ новой информацией, но Хедли всегда должен быть в курсе событий.