Сколько делает порядок влияния маркировок случая эффективность операторов переключения?

Не забывайте блог Scott Guthrie. Последние новости о MVC. "Официальный" сайт является двумя выпусками позади.

14
задан Jon Seigel 1 December 2009 в 16:41
поделиться

9 ответов

Некоторые факты для современного оборудования, такого как x86 или x86_64:

  • Безоговорочно взятая ветка почти не имеет дополнительных затрат, кроме декодирования. Если вам нужно число, это примерно четверть такта.
  • Условная ветвь, которая была правильно спрогнозирована, почти не требует дополнительных затрат.
  • Условная ветвь, которая не была правильно предсказана, имеет штраф, равный длина конвейеров процессора составляет примерно 12-20 тактов, в зависимости от оборудования.
  • Механизмы прогнозирования очень сложны. Циклы с небольшим количеством итераций (например, в Core 2 до 64) можно точно предсказать. Небольшие повторяющиеся шаблоны, такие как «взято-сделано-не принято-сделано», можно предсказать, если они не слишком длинные (IIRC 6 на Core2).

Вы можете узнать больше о предсказании переходов в руководстве Agner Fogs .

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

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

Существуют также механизмы прогнозирования для косвенных переходов.

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

Существуют также механизмы прогнозирования для косвенных переходов.

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

33
ответ дан 1 December 2019 в 06:10
поделиться

Ваш вывод относительно утверждений if не будет верным на большей части оборудования, с которым я знаком. Проблема не в том, что вы прыгаете, а в том, что вы ветвитесь. Код может идти двумя разными способами, в зависимости от результата сравнения. Это может остановить конвейер на большинстве современных процессоров. Предсказание ветвлений является обычным явлением и в большинстве случаев устраняет проблему, но не имеет ничего общего с вашим примером. Предиктор может одинаково хорошо предсказать, что сравнение будет ложным, так же как и истинным.

Как обычно, см. Википедию: Branch Predictor

7
ответ дан 1 December 2019 в 06:10
поделиться

Это зависит от обстоятельств. Компилятор будет использовать набор внутренних критериев, зависящих от реализации, чтобы решить, реализовывать ли переключатель как последовательность тестов типа if или как таблицу переходов. Это может зависеть, например, от того, насколько «компактным» является ваш набор меток case . Если значения меток case образуют «плотный» набор, компилятор, вероятно, с большей вероятностью будет использовать таблицу переходов, и в этом случае порядок меток case не имеет значения. Если он решит использовать то, что напоминает последовательность тестов if-else, порядок может иметь значение.

Имейте в виду, что тело switch представляет собой один большой оператор с case метки, обеспечивающие несколько точек входа в этот оператор. По этой причине,

6
ответ дан 1 December 2019 в 06:10
поделиться

Наклейки на корпусе следует заказывать наиболее эффективным способом для удобства чтения.

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

3
ответ дан 1 December 2019 в 06:10
поделиться

Я не уверен насчет компилятора C #, но я знаю, что в сборке оператор switch может быть запрограммирован как переход к определенной строке, а не оценивать выражение как оператор if . Поскольку в select у вас есть все константы, он просто обрабатывает случаи как номера строк, и вы переходите непосредственно к номеру строки (значению case), переданному без какой-либо оценки. Это делает порядок операторов case неважным.

2
ответ дан 1 December 2019 в 06:10
поделиться

Если вы поместите наиболее часто встречающиеся случаи первыми, это немного оптимизирует код, и из-за способа переключения статты работают же правда. Когда программа переходит в switch и находит случай, который является истинным, она выполняет его и нажимает break, который выйдет из цикла. Ваше мышление правильное.

Тем не менее, я думаю, что эта оптимизация довольно минимальна, и если она замедляет время разработки, вероятно, она того не стоит. Кроме того, если вам нужно радикально изменить поток программы, чтобы приспособиться к этому, вероятно, это того не стоит. Вы экономите максимум пару циклов и, вероятно, никогда не увидите улучшения.

-2
ответ дан 1 December 2019 в 06:10
поделиться

Полагаю, вы знаете, что это будет иметь значение только в том случае, если это точка доступа. Лучший способ узнать, является ли это горячей точкой, - запустить код, выполнить выборку счетчика программы и посмотреть, присутствует ли он там более 10% времени. Если это точка доступа, посмотрите, сколько времени уходит на переключение if или . Обычно это незначительно, если только ваш Блок 1 и / или Блок 2 почти ничего не ]. Для этого можно использовать профилировщик. Я просто несколько раз приостанавливаю его.

Если вы не знакомы с языком ассемблера, я бы предложил изучить его, достаточно, чтобы понять, что генерирует компилятор. Это интересно и не сложно.

1
ответ дан 1 December 2019 в 06:10
поделиться

Как говорили другие, это зависит от множества вещей, в том числе от количества случаев, способа оптимизации и архитектуры вы бежите. Для интересного обзора см. http://ols.fedoraproject.org/GCC/Reprints-2008/sayle-reprint.pdf

0
ответ дан 1 December 2019 в 06:10
поделиться

Я думаю, что даже ваша первоначальная предпосылка - что вы можете оптимизировать оператор if , переставив условное выражение, вполне может быть ошибочным. В неоптимизированной сборке вы можете обнаружить, что то, о чем вы говорите, имеет некоторую ценность - возможно. В общем случае вам придется совершить прыжок хотя бы один раз в любом случае, так что в любом случае нет никакого преимущества (в целом) в расположении условного выражения. Но это для неоптимизированных сборок, так кого волнует эта оптимизация?

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

Теперь, что касается оператора switch, я бы всегда используйте переключатель , когда он делает код более читабельным. Худшее, что компилятор должен сделать с оператором switch , который эквивалентен оператору if , - это сгенерировать тот же код. Для более чем нескольких случаев операторы switch обычно компилируются как таблица переходов. Но опять же, набор тестов if , которые сравнивают одну переменную с набором значений, вполне может быть распознан компилятором, и он будет делать то же самое. Однако я полагаю, что использование переключателя позволит компилятору гораздо легче распознать ситуацию.

Если вы действительно заинтересованы в том, чтобы получить максимальную отдачу от производительности этого условия, вы можете подумать об использовании чего-то вроде Управляемая оптимизация профиля MSVC (PGO или «pogo»), которая использует результаты прогонов профилирования для оптимизации генерации условных выражений. Я не знаю, есть ли у GCC аналогичные возможности.

Я предполагаю, что использование переключателя позволит компилятору гораздо легче распознать ситуацию.

Если вы действительно заинтересованы в том, чтобы получить максимальную отдачу от производительности этого условия, вы можете подумать об использовании чего-то вроде профиля MSVC Управляемая оптимизация (PGO или «pogo»), которая использует результаты прогонов профилирования для оптимизации генерации условных выражений. Я не знаю, есть ли у GCC аналогичные возможности.

Я предполагаю, что использование переключателя позволит компилятору гораздо легче распознать ситуацию.

Если вы действительно заинтересованы в том, чтобы получить максимальную отдачу от производительности этого условия, вы можете подумать об использовании чего-то вроде профиля MSVC Управляемая оптимизация (PGO или «pogo»), которая использует результаты прогонов профилирования для оптимизации генерации условных выражений. Я не знаю, есть ли у GCC аналогичные возможности.

3
ответ дан 1 December 2019 в 06:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: