эвристика c++ для оценки преимуществ встроенных функций

В c++, что является хорошей эвристикой для оценки преимуществ вычисления времени вставки функции, особенно когда функция вызывается очень часто и составляет >= 10% времени выполнения программы (например. функция оценки процесса грубой силы или стохастической оптимизации). Даже при том, что инлайнинг может быть в конечном счете вне моего контроля, мне все еще любопытно.

6 ответов


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


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


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

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

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

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


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

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


поведение здесь несколько зависит от компилятора. С рекурсивной функцией, очевидно, поведение встраивания теоретически может быть бесконечным. Ключевое слово "inline" - это только подсказка компилятору, он может выбрать его игнорировать, если он ничего не может с ним сделать. Некоторые компиляторы встроят рекурсивную функцию на определенную глубину.

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


наш опыт, 20+ лет написания вычислительно интенсивного C++, заключается в том, что вставка не является серебряной пулей. Вам действительно нужно профилировать свой код, чтобы увидеть, увеличит ли вставка производительность. Для нас кроме низкоуровневых 2D и 3D точечных и векторных манипуляций инлайнинг-это пустая трата времени. Вам гораздо лучше разработать лучший алгоритм, чем пытаться управлять тиканьем часов.