【发布时间】:2016-05-05 08:07:19
【问题描述】:
好的,所以我做了一个小修改,似乎对 haskell 产生了很大的影响。事情是这样的:
我为来自项目 euler 的 Prob 10 实施了埃拉托色尼筛法。事情是这样的:
primesBelowN :: Integer -> [Integer]
primesBelowN n = 2:3:filter f [6*k+i | k <- [1..(n-1)`div`6], i <- [-1, 1]]
where f x = foldr g True [2..truncate(sqrt(fromInteger x))]
where g t ac = (x `rem` t /= 0) && ac
main = print $ sum $ primesBelowN 2000000
使用 ghc 编译,运行时间为 8.95 秒:
$ ghc -O3 010SummationOfPrimes.hs
$ time 010SummationOfPrimes
142913828922
8.739u 0.122s 0:08.95 98.8% 0+0k 2384+0io 1pf+0w
我认为我可以利用 g 函数中的 haskell 惰性求值来优化代码。可以通过简单地将ac 作为&& 的第一个参数来完成(或者我认为),这样它就不会计算ac == False 的不等式:
primesBelowN :: Integer -> [Integer]
primesBelowN n = 2:3:filter f [6*k+i | k <- [1..(n-1)`div`6], i <- [-1, 1]]
where f x = foldr g True [2..truncate(sqrt(fromInteger x))]
where g t ac = ac && (x `rem` t /= 0)
main = print $ sum $ primesBelowN 2000000
令人惊讶的是,它使程序 慢了 4 倍!。现在的运行时间明显更大,为 30.94 秒:
$ ghc -O3 010SummationOfPrimes.hs
$ time 010SummationOfPrimes
142913828922
30.765u 0.157s 0:30.94 99.9% 0+0k 2384+0io 1pf+0w
我不知道出了什么问题...任何提示/建议/答案?提前致谢!
编辑
所以,当我翻倒另一个东西时,我正在玩这个。如果我像这样调整我的函数,看起来很容易陷入无限循环:
primesBelowN :: Integer -> [Integer]
primesBelowN n = 2:3:filter f [6*k+i | k <- [1..(n-1)`div`6], i <- [-1, 1]]
where f x = foldr g True [m | m <- [2..],
m <= truncate(sqrt(fromInteger x))]
where g t ac = (x `rem` t /= 0) && ac
main = print $ sum $ primesBelowN 2000000
在这种情况下,进程内存一直爆炸到巨大的数字(80Gig,在我杀死它之前),没有任何输出:
$ ghc -O3 010SummationOfPrimes.hs
$ time 010SummationOfPrimes
^C20.401u 7.994s 0:28.42 99.8% 0+0k 2384+0io 1pf+0w
任何想法现在出了什么问题?
【问题讨论】:
-
这是因为你在右折叠,但
&&的左参数很严格 -
@BenjaminHodgson 愿意解释一下吗?
-
@BenjaminHodgson 感谢您的回复,但我非常感谢您的详细说明。 Haskell新手在这里。 :)
-
你的候选人不包含任何2和3的倍数;你为什么要将它们除以 2、3、4、6、8、9、10、12、14、15 等? --- 您可以将
primesBelowN切换为:: Int -> [Int],并在sum之前使用map fromIntegral。 --- 另一件事是,primesBelowN 101给出了不完整的结果。为此,最好使用takeWhile (<= n) ...。 -
@WillNess 感谢您的评论。我的最终程序解决了这个问题:我没有除以任何偶数或复合数。我在 xs 中递归地调用了我自己的
primesBelowN列表并完成了它。工作速度提高了 8 倍!另外,关于 primesBelowN 101 部分,它不显示 101,因为truncate . sqrt只返回 10。只要它解决了问题!
标签: haskell optimization primes lazy-evaluation ghc