Haskell compiling with -O2 drastically increases memory usage

你。 提交于 2019-12-01 17:28:44

This is the full laziness "optimization" biting you. When it works right, it can provide an asymptotic improvement in run time. When it works wrong... This happens.

The full laziness transform moves constants out of bindings to the enclosing scope. In this case, it's picking up on the [1..(1073741824-1)] constant, and moving it to the enclosing scope. However, that's.. completely wrong. It causes it to be shared between the two calls, meaning that it can't stream efficiently the first time.

There is no reliable way to defeat the full laziness transformation, except for compiling without -O2.

The reason was explained by Carl really good and I don't think I can help you there any more.

But I can show you how to work around this.

First your g really just does sum up to 1073741823 and add f a.

There is a simple formula to sum up the numbers from 1 to n without that many additions (Gauss is said to have found it in primary-school):

sumUp :: (Integral a) => a -> a
sumUp n = n * (n+1) `div` 2

with this you can write

f x = x*x
g a = sumUp (1073741824-1) + f a
main = do putStrLn $ show $ foldl' (+) 0 $ map g [0,1]

remarks

You can hava a look at the link to see intuitively why this holds or try to find the proof yourself - it's really easy using induction :D

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!