Это продолжение моего предыдущего вопроса, на котором я спросил, почему потоковое слияние не пинги в определенной программе. Оказывается, проблема заключалась в том, что некоторые функции не были встроены, а флаг INLINE
улучшил производительность примерно на 17x
(что демонстрирует важность встраивания!).
Теперь обратите внимание, что в исходном вопросе я жестко запрограммировал 64
вызовы incAll
сразу. Теперь предположим, что вместо этого я создаю функцию nTimes
, которая вызывает функцию повторно:
module Main where
import qualified Data.Vector.Unboxed as V
{-# INLINE incAll #-}
incAll :: V.Vector Int -> V.Vector Int
incAll = V.map (+ 1)
{-# INLINE nTimes #-}
nTimes :: Int -> (a -> a) -> a -> a
nTimes 0 f x = x
nTimes n f x = f (nTimes (n-1) f x)
main :: IO ()
main = do
let size = 100000000 :: Int
let array = V.replicate size 0 :: V.Vector Int
print $ V.sum (nTimes 64 incAll array)
В этом случае просто добавление INLINE
pragma to nTimes
не поможет, потому что AFAIK GHC не выполняет встроенные рекурсивные функции. Есть ли какой-либо трюк, чтобы заставить GHC расширять nTimes
во время компиляции и, таким образом, восстановить ожидаемую производительность?