2010-09-13 5 views
36

Есть ли какой-либо переносной способ подсказки предсказания ветвления? Рассмотрим следующий пример:Подсказки для предсказания переносимых ветвей

if (unlikely_condition) { 
    /* ..A.. */ 
    } else { 
    /* ..B.. */ 
    } 

Является ли это по-другому, чем делать:

if (!unlikely_condition) { 
    /* ..B.. */ 
    } else { 
    /* ..A.. */ 
    } 

Или это единственный способ, чтобы использовать компилятор конкретные советы? (например, __builtin_expect on GCC)

Будут ли компиляторы обрабатывать условия if по-разному в зависимости от порядка условий?

+0

Интересно, может ли это быть что-то атрибуты C++ 0x для использования на условиях 'if'? Как 'if ([[маловероятно]] маловероятное_состояние) {...}'? В настоящее время синтаксис этого не позволяет. Он * does * однако разрешает 'if ([[маловероятно]] bool b = ...) {}'. Возможно, это можно было бы злоупотреблять :) –

+4

Код GNU содержит смехотворную сумму 'if (вероятно (...))' junk в полностью критическом для не-производительности коде, а IMO это действительно плохо. Во-первых, он не читается естественно на английском языке - это звучит так: «если это условие, скорее всего, будет истинным», а не «если это условие истинно, а это, вероятно, есть». А для другого это просто беспорядок. Если у вас нет особых критически важных условий, которые не будут компилироваться с 'cmov' или аналогичными уже, просто игнорируйте намеки на прогнозирование ветвлений. –

+0

@R .. Думаю, я понимаю, почему ядро ​​Linux завалено 'if (маловероятно (...))'. Они предпочитают ранние выходы, которые облегчают отслеживание потока кода. Если бы они этого не сделали, то предсказание статической ветви всегда терпело бы неудачу. –

ответ

25

канонический способ сделать статическое предсказание ветвлений, что if предсказывается не разветвленным (т.е. каждый if пункта выполняется, не else), и петли и назад - goto с. Поэтому не ставьте общий случай в else, если вы ожидаете, что статическое предсказание будет значительным. Обход незанятой петли не так прост; Я никогда не пробовал, но я полагаю, что предложение else должно работать довольно портативно.

Многие компиляторы поддерживают форму #pragma unroll, но по-прежнему необходимо защитить ее каким-то образом #if для защиты других компиляторов.

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

Как рекомендует GNU в документации для __builtin_expect, оптимизация на основе профиля превосходит намеки и с меньшими усилиями.

+0

И у VS тоже есть PGO, так что это беспроигрышный. :) – GManNickG

1

Просто соглашайтесь с тем, что вы делаете. Мне нравится использовать

if (!(someExpression)) 

Но компилятор должен относиться к этому в равной степени.

7

Оптимизация по своей сути является компилятором, поэтому для ее использования вам необходимо использовать функции компилятора. Сам язык не заботится о (или мандатной) оптимизации.

Итак, самое лучшее, что вы можете сделать без Расширения для компилятора организуют ваш код таким образом, чтобы ваши компиляторы «поступили правильно» без помощи. Но если вы хотите быть уверенным, подключитесь к расширениям компилятора. (Вы можете попробовать абстрагирования их за препроцессором, так что ваш код остается портативным.)

+4

Существует множество прецедентов для языка, предоставляющего подсказки оптимизации ('inline',' restrict', 'register'). Некоторые из них более точны, чем другие, в современных компиляторах. Не имеет значения, действительно ли какая-то конкретная реализация делает с ними что-либо: если есть разумные шансы на то, что кто-то сделает что-то полезное, тогда это будет приятная функция. Я считаю, что предсказание статического ветвления в основном не соответствует этому критерию, поэтому я не думаю, что это плохой вызов, чтобы его не учитывать. Это суждение о достоинствах дела, хотя и не совсем «нас не волнует оптимизация, когда-либо». –

+0

@Steve: Да, я думаю, я автоматически игнорирую их, поэтому я забываю о них. Ты прав. – GManNickG

+2

Я думаю, что 'ограничение', вероятно, стоит как преждевременная оптимизация. Это не принесет никакого вреда, это может привести к серьезным последствиям, предотвратив ужасные зависимости хранилища/нагрузки, и там, где это применимо, это, предположительно, документированное требование (как в «memcpy»), отражено ли это в источнике или нет. Другие (и в C++ 03), я согласен с вашим громким «meh» :-) –

15

В большинстве случаев следующий код

if (a) 
{ 
    ... 
} 
else 
{ 
    ... 
} 

фактически

evaluate(A) 

if (!A) 
{ 
    jmp p1 
} 

... code A 

    jmp p2 

p1: 

... code !A 

p2: 

Обратите внимание, что если А истинно, "код A" уже в трубопроводе. Процессор увидит команду «jmp p2» вперед и загрузит код p2 в конвейер.

Если A является ложным, «код! A» может быть не в pipleline, поэтому он может быть медленнее.

Выводы:

  1. делать если (X), если X является более вероятным, чем X
  2. попытка оценить как можно раньше, так что процессор может dynmically оптимизировать конвейер!.

:

evaluate(A) 

do more stuff 

if (A) 
    ... 
+0

понял! Пожалуйста, держите код «if» в фигурных скобках, даже если его одна строка. Это немного запутанно! – Ayyappa

+0

«попытайтесь оценить A как можно раньше, чтобы процессор мог динамически оптимизировать конвейер». - Не могли бы вы предоставить некоторые указания для этого заявления? Я хочу знать, как он это сделает. – Ayyappa

+0

Много информации здесь: http://download.intel.com/design/pentiumii/manuals/24281603.pdf –

1

Что случилось с проверкой для конкретного компилятора с помощью #ifdef и скрывая эти вещи за макропрограмме? Вы можете указать #define, чтобы развернуть это выражение в случаях, когда у вас нет компилятора, который поддерживает эти подсказки оптимизации. Недавно я сделал что-то подобное с явными кэшами, которые GCC поддерживает через встроенную функцию.

+0

Я сделал это. С более чем двумя или тремя компиляторами это может стать настоящим беспорядком, если разные компиляторы используют разные синтаксисы. –

Смежные вопросы