Какой из них быстрее? Вызов функции или условный оператор if? - PullRequest
4 голосов
/ 01 октября 2011

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

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

     class Shape
     {
        float Area()
        {
            if(type == SQUARE)
             {
                return length*length;
             }
            else if(type == RECTANGLE)
            {
             return length*breadth;
            }
        } 
     }

Один и тот же класс может быть написан так.

       class Shape
     {
        void SetAreaFunction(void *funcptr)//this function is used to set the current AreaFunc
        {
             CurrentAreaFunc = funcptr ;//this holds the pointer to current area func
        }
        float SqauareArea();//this will return square area
        float RectangleArea();//this will return rectangle area 
        float Area()
        {
            currentAreaFunc();
        } 
     }

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

Теперь дайте мне знать, что лучшеи «лучше оптимизированный код» в этом типе senarios (кстати, мне не нравится утверждение «преждевременная оптимизация - корень всего зла», поскольку оптимизация имеет свои преимущества, поэтому я считаю, что оптимизировать свой код!)

PS: Я не против, если кто-нибудь даст подробный обзор о том, «как плохое предсказание ветвления может быть», даже в коде сборки.

Обновление: после профилирования (аналогичный код выше),
Если Условие преуспело в этом типе senario.Can любой может дать причину для этого? Функциональный код вызова может быть предварительно выбран, так как нет кода Разветвления правильно? Но hпрежде чем он выглядит иначе ... разветвленный код выигрывает!: O Профилировано на Intel Mac Osx, GCC O3 / Os оптимизация.

Ответы [ 3 ]

9 голосов
/ 01 октября 2011

Вы заменили оператор if на косвенное.

Как для вашего оператора if, так и для косвенного обращения требуется доступ к памяти.

Однако оператор if приведет к короткому переходу - что, вероятноне сделает недействительным конвейер, в то время как косвенное обращение может сделать недействительным конвейер.

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

Трудно сказать, что быстрее, не проверяя его.Я предсказываю, что утверждение if победит.

Пожалуйста, поделитесь своими результатами!

3 голосов
/ 01 октября 2011

Более вероятно, что оптимизатор может применить свою магию к оператору if, а затем к динамически меняющемуся указателю на функцию.Просто предположим, что теоретически компилятору разрешено делать все, что он может доказать, не изменяет семантику.

Но в случае, если вы не вызываете функцию, а реализуете только ветвь (используя if в вашем случае) ЦП с большей вероятностью применяет свою магию , то есть переупорядочивает инструкции, выполняет предварительную выборку и тому подобное.Если между большинством процессоров будет вызван вызов функции, очень вероятно, что они "очистят" свои конвейеры, и оптимизация процессора будет невозможна.

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

Попробуйте измерить это самостоятельно.Назовите это 1M раз.С C ++ 11 используйте <chrono>, monothonic_clock::now().

Обновление : Мой опыт таков: не слишком оптимизируйте свой код, моя рука - очень вероятно, что высделать хуже.Пусть компилятор сделает всю работу, и для этого сделайте как можно больше кода видимым для него.Если вы это сделаете, вам определенно нужен профилировщик, попробуйте альтернативы, воспользуйтесь подсказками, которые некоторые из них предлагают вам.Но не забывайте: это нужно очень тщательно настроить.Только one измерение производительности - это скорость.Существует также читаемость , тестируемость и повторное использование и многие другие.И процитирую Дональда Кнута: «Преждевременная оптимизация - корень всего зла».

3 голосов
/ 01 октября 2011

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

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

Тем не менее, я помню Липпмана в его объектной модели C ++ со ссылкой на исследование, которое показало, что виртуальные функции (в основном указатели функций), по крайней мере, так же быстро переключаются между типами в реальных приложениях. Я не знаю деталей, но это где-то в книге.

...