Действительно ли функторы быстрее, чем указатели на функции?
Согласно Скотту Мейерсу, одна область, где С++ сияет над C, - это то, что объекты функции быстрее, чем указатели на функции. Он говорит, что это связано с тем, что функциональные объекты встроены, что увеличивает скорость.
У меня есть два вопроса:
-
Как мы можем проверить, что функциональные объекты, по сути, встроены? Можем ли мы проверить это на практике?
-
Влияет ли встраивание объектов-функций на используемый нами компилятор или все команды ведут себя так:
Ответы
Ответ 1
Стандарты С++ и C оставляют кучу свободы компиляторам. Компиляторы могут рассчитывать до 1 миллиарда между каждой инструкцией или только делать это, если целое число имеет в нем основное значение.
Достойные "реальные" компиляторы этого не делают. Это проблема качества выполнения.
Встраивание объектов функции в нечто вроде std::sort
- это то, что делает каждый настоящий компилятор. Чрезвычайно легко определить, что должно быть включено в эти случаи, поскольку информация типа содержит с собой код, необходимый для вложения.
Выполнение этого с помощью указателя функции сложнее. Выполнение этого указателя функции, где все было преобразовано в указатели void*
или char*
, еще сложнее.
Эффект от этого состоит в том, что на практике вызов C-стиля qsort
против вызова стиля std::sort
на С++ может привести к большому преимуществу для std::sort
.
qsort
примерно в 2 раза медленнее, чем std::sort
, как показано здесь, в смешной простой ситуации сортировки случайно упорядоченных целых чисел.
Проверка фактического выходного кода сборки в основном является деталью, и это большая работа для небольшого возврата. Принятие конкретных реальных примеров дает вам представление о том, насколько значительным является влияние.
Все 3 clang, gcc и MSVC, где можно сделать std::sort
, значительно быстрее, чем их qsort
. И поскольку это простая оптимизация, а оптимизация указателей функций на встроенные вызовы - нет, вы ожидаете, что менее крупные компиляторы не будут лучше, чем это в qsort
.
Ответ 2
- Как мы можем проверить, что функциональные объекты фактически встроены? Можем ли мы проверить это на практике?
Конечно, проверьте окончательно испущенный код ассемблера.
- Объекты функции inlining зависят от используемого компилятора, или все компиляторы ведут себя так:
В значительной степени это зависит от используемого уровня реализации компилятора и уровня оптимизации.
Так что нет, нет гарантии, что конкретные компиляторы (линкеры) ведут себя так.
Вызовы с помощью указателей функций не могут быть привязаны.
По его словам, функциональные объекты встроены, поэтому происходит увеличение скорости.
Объекты функции IMO "inline" должны лучше читать (или слышать, я не знаю, откуда этот цитат):
объекты функции могут быть встроены, тогда как вызовы с помощью указателей функций не могут.
Ответ 3
Да, объекты функций могут привести к более быстрому коду. Но единственный способ убедиться в этом.
-
Документация говорит: "GCC может по-прежнему не в состоянии встроить функцию по многим причинам, опция -Winline
может используется, чтобы определить, не была ли встроена функция, а почему нет."
-
Конечно, это будет зависеть от компилятора, версии, флагов и т.д. Иногда встраивание может быть контрпродуктивным (раздувание кода и т.д.), поэтому каждый компилятор имеет свой собственный набор правил, чтобы решить, должна ли функция встраиваемый. Кстати, ключевое слово inline
- это всего лишь подсказка, и некоторые библиотеки, такие как eigen, имеют трудное время для принудительной вставки.