Haskell中递归数组的内存使用情况

时间:2018-12-09 13:09:07

标签: haskell memory dynamic-programming

我有一个动态编程算法,我发现Haskell实现非常令人满意,因为它允许我递归定义主数组,如下所示:

fill :: Int -> Int -> Entry
fill 0 0 = Entry Origin 0.0
fill 0 j = ...
fill i 0 = ...
fill i j = f m i j

m :: Array (Int, Int) Entry
m = listArray dims [fill i j | (i, j) <- range dims]

其中f是一个中等复杂的函数,它返回到主数组mEntry类型只是带有小注释的Double

数据本身非常大,并且m最终具有约100M条目。该算法仍在快速发展,但在此过程中使用了约25GB的RAM。通过阅读,我了解到这是因为它保留了数组项的完整计算,而不是最终值,但是如果我切换到未装箱的数组,则无法像上面的示例中那样递归地定义它们。

有没有办法吃蛋糕(低内存占用)并吃掉它(递归定义)?

1 个答案:

答案 0 :(得分:1)

最后,我得到了未装箱的可变数组的合理结果,如下所示:

import Data.Array.ST as UM
import Control.Monad (forM_)

mbounds = ((0,0), (..., ...))
m = UM.runSTUArray $ do
    arr <- UM.newArray_ mbounds
    let set = UM.writeArray arr
    let get = UM.readArray arr
    let fill (0, 0) = do set (0, 0) 0.0
        fill (i, 0) = do top <- get (i-1, 0)
                         set (i, 0) (f top)
        fill (0, j) = do ...
        fill (i, j) = do ...
    forM_ (UM.range mbounds) fill
    return arr

仍然消耗了比我想要的更多的内存(〜4GB),但这是一个巨大的进步,我怀疑在重新运行探查器之后,我将寻找进一步削减它的方法。