Каковы хорошие эвристики для встроенных функций? - PullRequest
6 голосов
/ 25 января 2010

Учитывая, что вы пытаетесь оптимизировать только скорость, какова хорошая эвристика для принятия решения о включении функции или нет? Очевидно, что размер кода должен быть важен, но есть ли другие факторы, которые обычно используются, когда, скажем, gcc или icc определяют, встроить ли вызов функции? Была ли значительная академическая работа в этом районе?

Ответы [ 4 ]

8 голосов
/ 25 января 2010

В Википедии есть a несколько абзацев об этом, с некоторыми ссылками внизу:

  • Помимо проблем с размером памяти и кешем, еще одним соображением является давление регистра . С точки зрения компилятора «добавленные переменные из встроенной процедуры могут потреблять дополнительные регистры, а в области, где давление в регистре уже высокое, это может вызвать разлив, что вызывает дополнительные обращения к ОЗУ».

Языки с JIT-компиляторами и загрузкой классов времени выполнения имеют другие компромиссы, так как виртуальные методы статически не известны, однако JIT может собирать информацию о профилировании во время выполнения, такую ​​как частота вызова метода:

  • Проектирование, реализация и оценка оптимизаций в компиляторе Just-in-Time (для Java) рассказывает о методе встраивания статических методов и динамически загружаемых классов и его улучшениях в производительности.

  • Практика JUDO: Java в условиях динамической оптимизации утверждает, что их «политика встраивания основана на размере кода и информации о профилировании. Если частота выполнения записи метода ниже определенного порога, метод не является встроенным, потому что он рассматривается как холодный метод. Чтобы избежать взрыва кода, мы не включаем метод с размером байт-кода более 25 байтов ... Чтобы избежать встраивания по глубокой цепочке вызовов, вложение останавливается, когда накопленный размер встроенного байтового кода в цепочке вызовов превышает 40 байтов. " Несмотря на то, что они имеют информацию о профилировании во время выполнения (частоту вызова метода), они все же стараются избегать встраивания больших функций или цепочек функций для предотвращения раздувания.

Поиск в Google Scholar обнаруживает ряд статей, например

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

0 голосов
/ 25 января 2010

Насколько я видел, размер функции - это единственный фактор, используемый компиляторами для определения inline. Однако, если вы выполняете оптимизацию по профилю (PGO), я считаю, что компилятор может использовать другие переменные, такие как количество вызовов / время установления вызова.

0 голосов
/ 25 января 2010

В .NET в основном по размеру. Измерьте размер родительской функции и дочерней функции в скомпилированных байтах. Затем измерьте размер объединенной функции. Если объединенная функция меньше, то встраивание - хорошая идея.

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

0 голосов
/ 25 января 2010

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

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

...