Как использовать атрибут вероятности/маловероятности С++ 20 в операторе if-else

Этот вопрос касается функции [[likely]]/[[unlikely]] С++ 20, а не макросов, определяемых компилятором.

В этих документах (cppreference) приведен только пример их применения к коммутатору. -деловое заявление. Этот пример с переключателем отлично компилируется с моим компилятором (g++-7.2), поэтому я предполагаю, что компилятор реализовал эту функцию, хотя официально она еще не представлена ​​в текущих стандартах C++.

Но когда я использую их так: if (condition) [[likely]] { ... } else { ... }, я получаю предупреждение:

«предупреждение: атрибуты в начале оператора игнорируются [-Wattributes]».

Итак, как мне использовать эти атрибуты в операторе if-else?


person Leedehai    schedule 11.08.2018    source источник
comment
Если условие более вероятно в операторе if, поместите его первым   -  person Mercer    schedule 11.08.2018
comment
@Мерсер, я знаю; но это не то, что я спрашиваю..   -  person Leedehai    schedule 11.08.2018
comment
Это может быть реализовано лишь частично. Начните с проверки документации g++ и посмотрите, должна ли она поддерживаться.   -  person molbdnilo    schedule 11.08.2018
comment
Как сказал молбднилло; поскольку стандарт С++ 20 не завершен, не говоря уже об опубликовании, компилятор должен интегрировать новые функции по своему усмотрению.   -  person Mercer    schedule 11.08.2018
comment
У вас есть пример, который вы можете показать нам?   -  person SherylHohman    schedule 03.09.2018
comment
@Mercer Добавление наиболее вероятного условия к первому утверждению не эквивалентно использованию [[вероятно]]. Иногда компилятор меняет if(...) A else B на if (not ...) B else A. И это сломает конвейер, тогда он будет медленным. Вот пример: godbolt.org/z/WcPbPv< /а>   -  person HarryLeong    schedule 28.12.2019


Ответы (3)


Синтаксис основан на примере из Jacksonville'18 ISO C++ Report. правильно, но кажется, что это еще не реализовано:

if (a>b) [[likely]] {

10.6.6 Атрибуты вероятности [dcl. attr.likelihood] черновик

person user7860670    schedule 11.08.2018
comment
Хорошо.. так что в настоящее время компилятор только частично реализовал этот атрибут. - person Leedehai; 11.08.2018
comment
@Leedehai Я бы сказал, что в целом поддержка функций из будущего стандарта C ++ 20 на данный момент является чисто экспериментальной. - person user7860670; 11.08.2018
comment
Я нахожу странным, что в примере цикла while, представленном в этой ссылке, вероятный токен помещен после фигурной скобки, а не перед ней, как в остальных примерах. - person Mercer; 11.08.2018
comment
@Mercer, в последнем черновике ISO просто указано, что атрибуты могут быть назначены метке или оператору, поэтому кажется, что while (cond) [[likely]] { x(); y(); } и while (cond) { [[likely]] x(); y(); } одинаково действительны. Я не уверен, имеет ли смысл отмечать только первое утверждение как составное как вероятное, но, возможно, комитет знает больше, чем я - на самом деле это кажется вероятным, Знай, что я об этом думаю :-) - person paxdiablo; 11.08.2018
comment
Я только что просмотрел примеры в предоставленном черновике, и в нем полностью отсутствует пример цикла while. Время покажет. - person Mercer; 11.08.2018
comment
@Mercer, это, вероятно, разрешено, по крайней мере, на данный момент, в черновике говорится: маркеры атрибутов, вероятные и маловероятные, могут применяться к меткам или операторам (а операторы могут быть простыми или составными). Но я не уверен в значении одного оператора [[likely]] в последовательности, если только последовательность не может быть нарушена (возможно, с помощью исключения или выхода()?). Как говорится, время покажет... - person paxdiablo; 11.08.2018

Итак, как мне использовать эти атрибуты в операторе if-else?

Точно так же, как вы делаете, ваш синтаксис правильный в соответствии с примером, приведенным в проекте стандарта (упрощено, чтобы показать только соответствующие биты):

int f(int n) {
    if (n > 5) [[unlikely]] {
        g(0);
        return n * 2 + 1;
    }

    return 3;
}

Но вы должны понимать, что эта функция является относительно новой, поэтому в реализациях могут быть только заполнители, позволяющие вам устанавливать атрибуты. Это становится очевидным из вашего предупреждающего сообщения.


Вы должны также понимать, что, если определенные формулировки не изменятся между последним проектом и конечным продуктом, даже совместимые реализации могут игнорировать эти атрибуты. Они во многом являются предложениями для компилятора, такими как inline в C. Из этого последнего проекта n4762 (на момент этого ответа и с моим акцентом):

Примечание. Использование вероятного атрибута предназначено для того, чтобы позволить оптимизировать реализации для случая, когда пути выполнения, включающие его, сколь угодно более вероятны, чем любой альтернативный путь выполнения, который не включать такой атрибут в заявление или ярлык.

Обратите внимание на слово «разрешить», а не «заставить», «требовать» или «уполномочить».

person paxdiablo    schedule 11.08.2018
comment
Было бы НАМНОГО проще портировать существующий код на основе __builtin_expect, например. if (likely(a>b)) {, если бы мы могли указать атрибут внутри оператора if: if ([[likely]] a>b) {. - person rustyx; 19.03.2019

На сегодняшний день в cppreference указано, что, например, likely (курсив мой):

Применяется к оператору, чтобы позволить компилятору оптимизировать его для случая, когда пути выполнения, включающие этот оператор, более вероятны, чем любой альтернативный путь выполнения, который не включает такой оператор.

Это говорит о том, что место для размещения атрибута находится в операторе, что наиболее вероятно, т. е.:

if (condition) { [[likely]] ... } else { ... }

Этот синтаксис принимается, например, Visual Studio 2019 16.7.0 при компиляции с /std:c++latest.

person Gabriele Giuseppini    schedule 25.07.2020