考虑这段代码:
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
答案 0 :(得分:7)
如果我将isPrime
和primes
放在不同的模块中,我可以重现这一点。 (如果它们在同一模块中,但仍然与main
分开,我认为没有区别。)
添加{-# INLINE isPrime #-}
会给出与将所有三个模块放在一个模块中相同的性能,因此在这种情况下,GHC似乎需要轻推进行跨模块内联。
这是在GHC 7.0.2,Ubuntu 11.04,64位
答案 1 :(得分:1)
您是在GHCi内运行还是通过GHC编译?我只是尝试了一个实验,将所有定义保存在同一个文件中,将前两个移出,然后通过GHC编译并打开和关闭-O标志。我的机器上的不同组合之间没有明显的差异(使用GHC 7,所有组合在1秒内运行几毫秒)。