Почему использование функций, определенных в одном модуле, быстрее, чем функции, определенные в другом?
Рассмотрим этот блок кода:
isPrime primes' n = foldr (\p r -> p * p > n || (n `rem` p /= 0 && r)) True primes'
primes = 2 : filter (isPrime primes) [3..]
main = putStrLn $ show $ sum $ takeWhile (< 1000000) primes
который вычисляет сумму всех простых чисел ниже миллиона. Печать результата на моей машине занимает 0,468 секунды. Но если определения isPrime
а также primes
извлекаются в другой модуль, временная стоимость составляет 1,23 секунды, это почти в 3 раза медленнее.
Конечно, я могу копировать / вставлять различия везде, где это необходимо, но мне также любопытно, почему это происходит и как это решить.
[Править] Я использую GHC 7.0.3 (Windows 7 + MinGW). Код написан на EclipseFP (он использует Scion как IDE-сервер) и встроен в исполняемый файл с -O2
флаги.
Я также попытался собрать пакет вне IDE:
executable test
hs-source-dirs: src
main-is: Main.hs
build-depends: base >= 4
ghc-options: -O2
other-modules: Primes
executable test2
hs-source-dirs: src2
main-is: Main.hs
build-depends: base >= 4
ghc-options: -O2
Вот результат:
$ time test/test
37550402023
real 0m1.296s
user 0m0.000s
sys 0m0.031s
$ time test2/test2
37550402023
real 0m0.520s
user 0m0.015s
sys 0m0.015s
2 ответа
Я могу воспроизвести это, если я положу isPrime
а также primes
в разных модулях. (Если они находятся в том же модуле, но все еще отдельно от main
Я не вижу разницы).
Добавление {-# INLINE isPrime #-}
возвращает ту же производительность, что и все три в одном модуле, поэтому, похоже, что в этом случае GHC нужен толчок для выполнения межмодульного встраивания.
Это на GHC 7.0.2, Ubuntu 11.04, 64-битная версия
Вы запускаете это внутри GHCi или компилируете через GHC? Я только что попробовал эксперимент, сохранив все определения в одном файле, переместив первые два, и скомпилировав через GHC с включенным и выключенным флагом -O. На моей машине нет ощутимой разницы между различными комбинациями (все они запускаются всего за несколько миллисекунд в течение 1 секунды, используя GHC 7).