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

Рассмотрим этот блок кода:

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).

Другие вопросы по тегам