Есть ли причина не использовать прагму INLINABLE для функции? - PullRequest
44 голосов
/ 15 марта 2012

Документация гласит:

Прагма {- # INLINABLE f # -} для функции f имеет следующее поведение:

  • В то время как INLINE говорит «пожалуйста, вставьте меня», INLINABLE говорит «не стесняйтесь, вставьте меня; используйте ваше усмотрение». Другими словами, выбор остается за GHC, который использует те же правила, что и для функций без прагмы. В отличие от INLINE, это решение принимается на месте вызова и поэтому будет зависеть от порога встраивания, уровня оптимизации и т. Д.

  • Как и INLINE, прагма INLINABLE сохраняет копию исходной RHS для целей вставки и сохраняет ее в файле интерфейса независимо от размера RHS.

  • Один из способов использования INLINABLE связан со специальной встроенной функцией (раздел 7.18, «Специальные встроенные функции»). Вызов inline f очень старается встроить f. Чтобы убедиться, что f может быть встроенным, рекомендуется пометить определение f как INLINABLE, чтобы GHC гарантировал раскрытие разворачивания независимо от его размера. Более того, аннотируя f как INLINABLE, вы гарантируете, что исходная RHS f встроена, а не какая-либо случайно оптимизированная версия оптимизатора f GHC.

  • Прагма INLINABLE также работает со SPECIALIZE: если вы пометите функцию f как INLINABLE, вы можете впоследствии SPECIALIZE в другом модуле (см. Раздел 7.16.8, «Прагма SPECIALIZE»).

  • В отличие от INLINE, можно использовать прагму INLINABLE в рекурсивной функции. Основная причина заключается в том, чтобы разрешить дальнейшее использование SPECIALIZE

В чем его недостаток?

Делает ли он интерфейсные файлы намного, намного больше? Это делает компиляцию намного медленнее?

Есть ли причина, по которой я не должен ставить прагму INLINABLE для каждой экспортируемой функции, которую я пишу? Есть ли причина, по которой GHC не помещает прагму INLINABLE в каждую экспортируемую функцию, которую я пишу?

1 Ответ

49 голосов
/ 15 марта 2012

Существует три различия между использованием INLINABLE и отсутствием прагмы вообще:

  • Без INLINABLE определение, которое идет в файле интерфейса, - это код после оптимизации, тогда как с INLINABLE это код, который вы написали (более или менее). В частности, без INLINABLE GHC может включить другие функции в определение функции.

  • Без INLINABLE GHC пропустит определение из файла интерфейса, если оно слишком большое. Если в правую часть вставлена ​​какая-то другая функция, это может легко переместить ее за предел.

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

...