По умолчанию в корпусе коммутатора

The below is the code which I need to optimize and planned that it would be good to move to switch. But I can compare in case. So I planned to make the comaparision ( len > 3 ) as default case.

If I make the comparision part ( len > 3 ) as default case and add default as first in swith will it be faster?

Или как я могу сделать код ниже в качестве оператора switch?

            if ( len > 3 ) {
                    which will happen more often;
            }               
            else if ( len == 3 ) {
                    next case which may occur often;
            } else if ( len == 2 ) {        
                   the next priority case;
            } else {
                    and this case occurs rarely;
            }
4
@chris Спасибо за ваш ответ. Но я помню, что я где-то учился, даже если у вас есть еще два других, если лучше переходить к переключению?
добавлено автор 2vision2, источник
Спасибо за все ваши ответы, и я бы принял ответ @icepack как лучший.
добавлено автор 2vision2, источник
Ну, конечно, это может выглядеть лучше, если это действительно возможный ход. Это не так.
добавлено автор chris, источник
Вы не можете переместить диапазон от 4 до максимального значения в коммутатор. Для этого нужны метки для случаев компиляции.
добавлено автор chris, источник
@JasonD, я полагаю, вы могли бы поместить как > 3 , так и else в default . Однако действительно не стоит пытаться включить > 3 как часть случаев.
добавлено автор chris, источник
@chris на самом деле я не совсем думал об этом - я добавил ответ, чтобы показать, что я имею в виду, хотя я согласен, что в этом случае это почти наверняка не подходит.
добавлено автор JasonD, источник
@chris, если выполнение этого действительно было критическим (что я вроде сомневаюсь), превращение неравенства в прямое (переключаемое) сравнение вполне возможно.
добавлено автор JasonD, источник
@ 2vision2 может быть более читабельным и масштабируемым, но это не связано с производительностью
добавлено автор SomeWittyUsername, источник

6 ответы

Возможно нет. И if ... else и switch ... case являются конструкциями высокого уровня. То, что замедляет вас, - это предсказание ветвей. Чем лучше ваш прогноз, тем быстрее будет работать ваш код. Вы должны поместить свой самый встречный случай в первый , если , второй в else if и т. Д., Как и вы писали. Для switch результат зависит от внутренней реализации компилятора, которая может изменять порядок дел, несмотря на ваш собственный заказ. default должен быть фактически зарезервирован для менее встречающихся ситуаций, потому что остальная часть условий должна быть проверена, прежде чем вернуться к default .

Чтобы все это сделать, оптимальное использование if ... else является оптимальным, если вы зададите условия в правильном порядке. Что касается switch ... case , то он специфичен для компилятора и зависит от применяемых оптимизаций.

Также обратите внимание, что switch ... case более ограничен, чем if ... else , поскольку он поддерживает только простое сравнение значений.

6
добавлено
@icepack Вам нужно сортировать, чтобы определить, плотно ли дела или нет. Вам нужны случаи сортировки, если вы собираетесь использовать таблицу перехода. И вам нужны отсортированные случаи, если вы собираетесь выполнять двоичный поиск. В каждом компиляторе, с которым я когда-либо работал, первое, что вы делаете, это сортировать дела.
добавлено автор James Kanze, источник
@icepack Даже без оптимизации каждый компилятор, над которым я работал, запускает сортировку элементов в коммутаторе, чтобы найти max и min, и решить, плотно ли они или нет. Таким образом, порядок в коммутаторе не будет иметь никакого эффекта. Для версии if / else она может быть, если вы не оптимизируете. Но если производительность важна, почему бы вам не оптимизировать. И с выходом профилировщика компилятор выберет то, что лучше всего для фактических наблюдаемых частот.
добавлено автор James Kanze, источник
Этот ответ просто ошибочен. Вообще говоря, порядок, в котором вы помещаете дела в коммутатор, не имеет значения; первое, что делает компилятор, это сортировать случаи и обрабатывать их в отсортированном порядке. (Но это зависит от компилятора. Большинство современных компиляторов имеют опции, которые позволяют им использовать выход профилировщика для реорганизации кода. В таких случаях совершенно неуместно, как вы его пишете, компилятор пойдет правильно).
добавлено автор James Kanze, источник
@icepack stackoverflow.com/questions/14067547/… Отправленный здесь и нашел некоторые интересные ссылки тоже ... jus посмотреть. Благодарю.
добавлено автор 2vision2, источник
@Angew начал обсуждение здесь. stackoverflow.com/questions/14067547/…
добавлено автор 2vision2, источник
@Angew Я планирую сделать это как еще один вопрос. Что сказать?
добавлено автор 2vision2, источник
@Angew, чтобы добавить еще несколько пунктов ypur, лучше дать случай в некотором сортированном способе сделать работу переключателя быстрее?
добавлено автор 2vision2, источник
@Инже это то, что я читал «бинарный поиск». Интересно. Не могли бы вы добавить некоторые ссылки, если это возможно?
добавлено автор 2vision2, источник
Во всяком случае, thnaks ... Я просто хочу знать, как внутренне реализован или работает коммутатор. Я читал некоторые, где я не мог найти источник, где я читал. Извините, что беспокою вас больше. \
добавлено автор 2vision2, источник
Я не говорю о том, как работает внутренне. Он уверен, что он намного быстрее, чем другой, если лестница. а также быстрее, потому что он будет выбирать случай, используя внутренние методы сортировки?
добавлено автор 2vision2, источник
Спасибо за ваш ответ. есть случай, когда коммутатор будет выбирать правильный случай в первом экземпляре. Я читал это где-то. Но я не уверен. Я предполагаю, что какой-то kindda sortin используется в swith. исправьте меня, если я ошибаюсь.
добавлено автор 2vision2, источник
AFAIK, некоторые компиляторы фактически «реализуют» switch с достаточным числом случаев в виде двоичного поиска, поэтому он может быть лучше, чем просто линейный компилятор if ... else .
добавлено автор Angew, источник
@icepack Мне рассказал друг, который провел некоторое исследование в области оптимизации в рамках своей магистерской диссертации. В то время, , , было проведено исследование, показывающее, что оно окупилось. Но я понятия не имею, насколько это справедливо сейчас.
добавлено автор Angew, источник
@Angew Интересное замечание. Это должно быть очень возможно, поскольку аргумент switch является целым числом. Но это вызывает другой вопрос - действительно ли это оптимизация? Двоичный поиск приведет к поисковому запросу O (logn) для каждой опции, но это полностью игнорирует предсказание ветвления, поэтому упорядочение случаев по порядку появления может привести к лучшим результатам. Интересная тема, хотя
добавлено автор SomeWittyUsername, источник
@JamesKanze Я частично согласен и отредактировал ответ. Однако вы противоречите себе - либо порядок не имеет значения, либо зависит от компилятора, но не для обоих. Я предполагаю, что в простейшем случае для ссылочного компилятора без какой-либо оптимизации порядок обработки будет просто линейным.
добавлено автор SomeWittyUsername, источник
@Angew это, вероятно, очень специфично для использования.
добавлено автор SomeWittyUsername, источник
В стандарте C не указывается, как должен быть реализован переключатель . Хотя это почти наверняка анализируется на конструкцию, похожую на длинный if..else
добавлено автор SomeWittyUsername, источник
Прогон кода проверяет первый case , после этого второй и т. Д. Таким образом, вы можете «сортировать» случаи по порядку появления, от высокого до низкого
добавлено автор SomeWittyUsername, источник
@ 2vision2 Пойдите для этого. Вероятно, есть некоторые сведения, которые люди могут предоставить. Вы также можете попробовать cs.stackexchange.com
добавлено автор SomeWittyUsername, источник
@JamesKanze Существует много случаев, когда сортировка будет только ухудшать производительность, поэтому я не буду так категоричен
добавлено автор SomeWittyUsername, источник

Хотя вы согласились с тем, что, вероятно, лучший ответ, я хотел бы предоставить альтернативу.

Обратите внимание, что стандартная оговорка применяется - оптимизация - это не оптимизация, если вы не профилировали свой код.

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

void doSomething(int len)
{
    static const char* str[] =
    {   "%2d > 3\n",
        "%2d < 2\n",
        "%2d = 2\n",
        "%2d = 3\n"
    };

    int m1 = (len-2)>>31;
    int m2 = (len-4)>>31;

    int r = (len & m2 & ~m1) + !!m1;

    printf(str[r],len); 
}

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

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

3
добавлено
Интересно, что вы можете избежать любого ветвления, но по какой цене. Учитывая количество дополнительных операций, и тот факт, что одно условие гораздо чаще, чем другие, хороший компилятор будет устраивать, чтобы не было никакого ветвления (предполагая, что правильно спрогнозированная ветка действительно дороговата) , поэтому все вышеизложенное действительно достигает обфускации.
добавлено автор James Kanze, источник
привет Джейсону. Thnaks много для вашего ответа. И это интересно. Он поощряет учащихся, таких как я, часто посещать SO.
добавлено автор 2vision2, источник
Интересно, я понимаю, что вы имели в виду сейчас. Я не думал о синтаксисе коммутатора. Как недостойный программист!
добавлено автор chris, источник
@JamesKanze Как я сказал в верхней части, это не оптимизация, если вы не профилировали. Тем не менее, я, безусловно, работал с компиляторами, для которых это было бы победой. Но при условии, что любой случай без профилирования - глупость.
добавлено автор JasonD, источник
+1 для приятной альтернативы
добавлено автор Caribou, источник

вы не можете перемещать сравнения в оператор switch. Он использует одиночные проверки для своих выборов .. то есть:

switch (len) {

    case 1:
       //do case 1 stuff here
    break;
    case 2:
       //do case 2 stuff here
    break;
    case 3:
       //do case 3 stuff here
    break;
}

use breaks to prevent the case statements from running into each other read more here

ваш код будет «оптимизирован», поскольку он будет в текущем состоянии.

2
добавлено

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

В вашем случае переключатель, вероятно, будет выглядеть так:

switch ( len ) {
case 2:
   // ...
    break;

case 3:
   // ...
    break;

default:
    if ( len > 3 ) {
       //...
    } else {
       //...
    }
}

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

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

1
добавлено
спасибо за Ваш ответ
добавлено автор 2vision2, источник

Если вы беспокоитесь о скорости, правда в том, что ваши операторы if ... else или switch ... case не будут иметь реального влияния на скорость вашего приложения, если только у вас их сотни. Места, где вы теряете скорость, находятся в ваших итерациях или петлях. Чтобы конкретно ответить на ваш вопрос, вы не можете преобразовать инструкцию if ... else в оператор switch ... case с первым кодом default ; но с учетом сказанного, если вы перешлите в switch ... case , тогда вы будете запускать их с одинаковой скоростью (разница слишком мала, чтобы быть подхваченной обычными инструментами бенчмаркинга).

1
добавлено
Спасибо за ваш ответ
добавлено автор 2vision2, источник
if if else или case switch в цикле, это будет иметь очень реальное влияние
добавлено автор SomeWittyUsername, источник
Я думаю, что это будет зависеть от размера цикла. Но в этом случае есть только четыре условия для проверки; разница будет иметь много знаков после запятой и на самом деле не является областью, в которой должно быть внимание разработчика.
добавлено автор Akash, источник

Вы можете использовать диапазон в случае:

switch (len) {
  case 3 ... INT_MAX:
   //...
    break;
  case 2:
   //...
    break;
  default:
   //...
    break;
 }

Изменить: но это расширение, предоставляемое GCC ...

0
добавлено
@Caribou, как показывает ваша ссылка, компиляция с параметром -pedantic предупреждает о «нестандартной» (gcc 4.7.2); слишком плохо это не в стандарте, хотя
добавлено автор piwi, источник
мой плохой, не знал, что
добавлено автор piwi, источник
Я согласен на самом деле - интересно, может ли компилятор сделать какую-то оптимизацию, используя это? или он становится таким же, как код «if..else». Один для моего кофе-брейка может быть :)
добавлено автор Caribou, источник
это хорошая конструкция :) Я просто этого не видел и мне было любопытно
добавлено автор Caribou, источник
В нем говорится, что это не стандарт здесь: это все еще так? stackoverflow.com/questions/5924681/& hellip;
добавлено автор Caribou, источник
pro.cxx
pro.cxx
3 049 участник(ов)

C/C++ chat 0. Простые вопросы, лабы и о IDE — в чат новичков @supapro 1. Не хамим, не переходим на личности, не вбрасываем утверждения без доказательств 2. No Ads, offtop, flood Объявления о вакансиях и евенты - в лс @AlexFails https://t.me/ProCxx/259155

supapro.cxx
supapro.cxx
1 925 участник(ов)

Чат для тех, кто немного знает C++, простые вопросы по реализации, синтаксису и ide – сюда, а для другого есть: /Главный чат по серьезным вопросам — @ProCxx /Чат по обсуждению всего — @fludpac

C++ Russia
C++ Russia
384 участник(ов)

Сообщество разработчиков C++ в Telegram.

cxx.Дискуссионная
cxx.Дискуссионная
298 участник(ов)

это не двач, общайтесь вежливо; разговор на почти любые темы; Не согласны с баном? В лс @AlexFails, @ivario

C++ для маленьких и тупых
C++ для маленьких и тупых
105 участник(ов)

Лоу левел (по среднему IQ участников) чатик ExtremeCode @extremecode Флудилка @extremecode_rest