Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Optimization 具有参数传递样式的Haskell堆问题_Optimization_Haskell_Profiling_Lazy Evaluation_Heap Memory - Fatal编程技术网

Optimization 具有参数传递样式的Haskell堆问题

Optimization 具有参数传递样式的Haskell堆问题,optimization,haskell,profiling,lazy-evaluation,heap-memory,Optimization,Haskell,Profiling,Lazy Evaluation,Heap Memory,下面是一个简单的程序,让我大吃一惊: intersect n k z s rs c | c == 23 = rs | x == y = intersect (n+1) (k+1) (z+1) (z+s) (f : rs) (c+1) | x < y = intersect (n+1) k (z+1) s rs c | otherwise = intersect n (k+1) z s rs c where x = (2*n*n) + 4 * n

下面是一个简单的程序,让我大吃一惊:

intersect n k z s rs c
  | c == 23   = rs
  | x == y    = intersect (n+1) (k+1) (z+1) (z+s) (f : rs) (c+1)
  | x < y     = intersect (n+1) k (z+1) s rs c
  | otherwise = intersect n (k+1) z s rs c
    where x = (2*n*n) + 4 * n
          y = (k * k + k )
          f = (z, (x `div` 2), (z+s))
p = intersect 1 1 1 0 [] 0

main = do
  putStr (show p)
相交n k z s rs c
|c==23=rs
|x==y=相交(n+1)(k+1)(z+1)(z+s)(f:rs)(c+1)
|x
程序所做的是计算两个无穷级数的交点,当它达到23个元素时停止。但这对我来说并不重要

有趣的是,据我所知,这里应该没有太多的东西。函数intersect是递归函数,所有递归都写为尾部调用。状态是在参数中累积的,并且没有太多。5个整数和一小部分元组

如果我是一个博彩的人,我会打赌,在我进行递归时,在参数中不知何故建立了thunk,特别是在没有对给定递归求值的参数上。但那只是一种疯狂的预感


这里真正的问题是什么?如何修复它呢?

如果堆有问题,请按如下方式运行:

$ ghc -O2 --make A.hs -prof -auto-all -rtsopts -fforce-recomp
[1 of 1] Compiling Main             ( A.hs, A.o )
Linking A.exe ...
{-# LANGUAGE BangPatterns #-}

intersect n k !z !s rs c
  | c == 23   = rs
  | x == y    = intersect (n+1) (k+1) (z+1) (z+s) (f : rs) (c+1)
  | x < y     = intersect (n+1) k (z+1) s rs c
  | otherwise = intersect n (k+1) z s rs c
    where x = (2*n*n) + 4 * n
          y = (k * k + k )
          f = (z, (x `div` 2), (z+s))

p = intersect 1 1 1 0 [] 0

main = do
  putStr (show p)
当运行时:

$ ./A.exe +RTS -M1G -hy
生成
A.hp
输出文件:

$ hp2ps -c A.hp
像这样:

因此,堆中充满了
Integer
,这表明函数的累积参数中存在一些问题——所有
Integer
都在这里

修改函数,使其在lazy
Integer
参数中严格(基于您从未检查其值的事实),如下所示:

$ ghc -O2 --make A.hs -prof -auto-all -rtsopts -fforce-recomp
[1 of 1] Compiling Main             ( A.hs, A.o )
Linking A.exe ...
{-# LANGUAGE BangPatterns #-}

intersect n k !z !s rs c
  | c == 23   = rs
  | x == y    = intersect (n+1) (k+1) (z+1) (z+s) (f : rs) (c+1)
  | x < y     = intersect (n+1) k (z+1) s rs c
  | otherwise = intersect n (k+1) z s rs c
    where x = (2*n*n) + 4 * n
          y = (k * k + k )
          f = (z, (x `div` 2), (z+s))

p = intersect 1 1 1 0 [] 0

main = do
  putStr (show p)
{-#语言模式}
交叉点n k!Zs rs c
|c==23=rs
|x==y=相交(n+1)(k+1)(z+1)(z+s)(f:rs)(c+1)
|x
现在,您的程序在常量空间中运行,并包含您正在生成的参数列表(尽管在任何合理的时间内都不会因
c==23而终止)


如果可以反转结果列表,则可以利用Haskell的惰性,在计算时返回列表,而不是将其作为累加参数递归传递。这不仅可以让您在计算列表时使用和打印列表(从而消除一个空间泄漏),还可以考虑您希望从
相交的元素数量:

{-# LANGUAGE BangPatterns #-}

intersect n k !z s
  | x == y    = f : intersect (n+1) (k+1) (z+1) (z+s)
  | x < y     = intersect (n+1) k (z+1) s
  | otherwise = intersect n (k+1) z s
    where x = (2*n*n) + 4 * n
          y = (k * k + k )
          f = (z, (x `div` 2), (z+s))
p = intersect 1 1 1 0

main = do
  putStrLn (unlines (map show (take 23 p)))

我觉得这两个系列没有交叉点。试着减少c并打印出n和k。它们相交不多,但相交足够多。如果我将c减少到10,程序将返回一个眼球链接。但即便如此,如果程序没有因为c==23从未满足而终止,它不应该永远在常量空间中递归吗?我希望我能+2这是一个分离部分的好例子。