эвристика c ++ для оценки преимуществ встраивания функций - PullRequest
12 голосов
/ 18 августа 2011

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

Ответы [ 6 ]

6 голосов
/ 18 августа 2011

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

1 голос
/ 18 августа 2011

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

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

1 голос
/ 18 августа 2011

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

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

* РЕДАКТИРОВАТЬ после комментария о том, что рекурсия не предназначена, а скорее итерация *

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

1 голос
/ 18 августа 2011

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

0 голосов
/ 18 августа 2011

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

0 голосов
/ 18 августа 2011

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

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

...