我有一个简单的问题:给定一个整数列表,读第一行为N
。然后,读取下N行并返回它们的总和。重复,直到N
= 0提高分块列表的性能
我的第一种方法是用这样的:
main = interact $ unlines . f . (map read) . lines
f::[Int] -> [String]
f (n:ls)
| n == 0 = []
| otherwise = [show rr] ++ (f rest)
where (xs, rest) = splitAt n ls
rr = sum xs
f _ = []
但它相对较慢。我已经用它
ghc -O2 --make test.hs -prof -auto-all -caf-all -fforce-recomp -rtsopts
time ./test +RTS -hc -p -i0.001 < input.in
凡input.in
是一个测试输入,其中第一行是10万,其次是100K的随机数,其次是0。我们可以在下面,它的使用澳图看异型(N)内存:
EDITED:我原来的问题是比较2点相同慢的方法。我已经更新了它与下面
最佳进场现在比较,如果我做的和反复,而不是调用sum
,我得到的内存
{-# LANGUAGE BangPatterns #-}
main = interact $ unlines . g . (map read) . lines
g::[Int] -> [String]
g (n:ls)
| n == 0 = []
| otherwise = g' n ls 0
g _ = []
g' n (l:ls) !cnt
| n == 0 = [show cnt] ++ (g (l:ls))
| otherwise = g' (n-1) ls (cnt + l)
我恒量试图理解第一个例子中导致性能损失的原因。我会猜想所有可能会被懒惰评估的东西?
未经测试的猜测:或许您在第一个示例中对'read'的两次调用不使用相同的类型,例如有一些“整数”与“整数”问题。 (编辑:这个评论是关于问题的以前的版本) – 2014-09-21 21:15:01