簡體   English   中英

恆定空間中的單聲道折疊

[英]Monadic Fold in Constant Space

如何在恆定空間中使用單子動作折疊懶惰列表? 我要解決的問題是聚合一個大文件,我相信出於性能考慮,我需要可變性。 我在ST中使用可變向量來實現一個實現,但是它使用了過多的內存。 以下是我正在嘗試的示例。 我還對Conduit進行了簡短的實驗,但這似乎沒有任何改善。

ST forM_:

import Control.Monad (forM_)
import Control.Monad.ST.Trans as STT
import Control.Monad.Identity as Identity

testST :: Int
testST = do
  Identity.runIdentity $ STT.runST $ do
    a <- STT.newSTRef 0
    forM_ [1..10000000] (\x -> do
        a' <- STT.readSTRef a
        STT.writeSTRef a (a' + x)
      )
    STT.readSTRef a

導管:

import Data.Conduit (($=),(=$),($$))
import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL

testCL :: IO Int
testCL = CL.sourceList [1..10000000] $$ CL.foldM (\a x -> return (a + x)) 0

問題不在於褶皺,而在於褶皺主體。 這個程序分配了很多:

testST = runST $ do
    ref <- newSTRef 0
    forM_ [1..10000000] $ \x -> do
         val <- readSTRef ref
         writeSTRef ref (val + x)
    readSTRef ref

該程序的唯一區別在於writeSTRef行,它幾乎不分配任何內容:

testST = runST $ do
    ref <- newSTRef 0
    forM_ [1..10000000] $ \x -> do
        val <- readSTRef ref
        writeSTRef ref $! val + x
    readSTRef ref

這兩段代碼之間的區別很好地說明了正在發生的事情:在前一個代碼中,您正在創建對深度嵌套的thunk的引用,該thunk具有10000000層+的應用程序; 而后者在每一步都壓扁了重擊。

順便說一句,這個常見的陷阱是modifySTRef的文檔中明確modifySTRef

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM