为什么使用在同一模块中定义的函数比在另一个模块中定义的函数更快?

时间:2011-09-13 12:17:07

标签: haskell module modularity optimization

考虑这段代码:

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 秒。但如果将isPrimeprimes的定义提取到另一个模块中,则时间成本 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 个答案:

答案 0 :(得分:7)

如果我将isPrimeprimes放在不同的模块中,我可以重现这一点。 (如果它们在同一模块中,但仍然与main分开,我认为没有区别。)

添加{-# INLINE isPrime #-}会给出与将所有三个模块放在一个模块中相同的性能,因此在这种情况下,GHC似乎需要轻推进行跨模块内联。

这是在GHC 7.0.2,Ubuntu 11.04,64位

答案 1 :(得分:1)

您是在GHCi内运行还是通过GHC编译?我只是尝试了一个实验,将所有定义保存在同一个文件中,将前两个移出,然后通过GHC编译并打开和关闭-O标志。我的机器上的不同组合之间没有明显的差异(使用GHC 7,所有组合在1秒内运行几毫秒)。