Есть ли причина не использовать INLINABLE прагма для функции?
В документации указано:
An {- # INLINABLE f # -} прагма для функции f имеет следующее поведение:
-
В то время как INLINE говорит: "Пожалуйста, включите меня", INLINABLE говорит: "Не стесняйтесь меня, используйте свое усмотрение". Другими словами, выбор остается для GHC, который использует те же правила, что и для функций без прагмы. В отличие от INLINE, это решение принимается на сайте вызова и поэтому будет зависеть от порога вложения, уровня оптимизации и т.д.
-
Как и INLINE, прагма INLINABLE сохраняет копию оригинальной RHS для встраивания целей и сохраняется в файле интерфейса независимо от размера RHS.
-
Один из способов использования INLINABLE - в сочетании со специальной встроенной функцией (раздел 7.18, "Специальные встроенные функции" ). Вызов inline f очень сильно пытается встроить f. Чтобы убедиться, что f может быть встроен, рекомендуется пометить определение f как INLINABLE, чтобы GHC гарантировал возможность разоблачения независимо от того, насколько он большой. Кроме того, аннотируя f как INLINABLE, вы гарантируете, что f оригинальная RHS встроена, а не какая-либо оптимизированная оптимизированная версия оптимизатора GHC.
-
ПРОГРАММА INLINABLE также работает со SPECIALIZE: если вы помечаете функцию f как INLINABLE, вы можете впоследствии СПЕЦИАЛИЗИРОВАТЬСЯ в другом модуле (см. раздел 7.16.8, "СПЕЦИАЛИЗАЦИЯ прагмы" ).
-
В отличие от INLINE, можно использовать INLINABLE прагму для рекурсивной функции. Основная причина заключается в том, чтобы впоследствии использовать SPECIALIZE
В чем его недостаток?
Он делает файлы интерфейса намного, намного больше? Делает ли компиляцию намного медленнее?
Есть ли какая-то причина, по которой я не должен помещать INLINABLE прагму для каждой экспортируемой функции, которую я пишу? Есть ли какая-либо причина, по которой GHC не помещает INLINABLE прагму для каждой экспортируемой функции, которую я пишу?
Ответы
Ответ 1
Существуют три различия между использованием INLINABLE и отсутствием прагмы:
-
Без INLINABLE определение, которое идет в файле интерфейса, является кодом после оптимизации, тогда как с INLINABLE это код, который вы написали (более или менее). В частности, без INLINABLE, GHC может включить другие функции в определение функции.
-
Без INLINABLE, GHC опустит определение из файла интерфейса, если оно слишком велико. Если какая-то другая функция вставлена в правую сторону, это может легко подтолкнуть ее к пределу.
-
INLINABLE также включает некоторые умные механизмы, которые автоматически специализируются на перегруженных функциях, где они используются, и разделяют специализированные версии с другими модулями, которые транзитно импортируют модуль, в котором была создана специализированная версия.