gpt4 book ai didi

haskell - 为什么我的 Haskell 程序以内存不足错误结束?

转载 作者:行者123 更新时间:2023-12-04 18:45:09 25 4
gpt4 key购买 nike

我正在尝试编写一个 Haskell 程序来解析巨大的文本文件(大约 14Gb),但我无法理解如何让它从内存中释放未使用的数据,或者在 foldr 期间不使堆栈溢出。下面是程序源码:

import qualified Data.ByteString.Lazy.Char8 as LBS
import qualified Data.ByteString.Lex.Lazy.Double as BD
import System.Environment


data Vertex =
Vertex{
vertexX :: Double,
vertexY :: Double,
vertexZ :: Double}
deriving (Eq, Show, Read)

data Extent =
Extent{
extentMax :: Vertex,
extentMin :: Vertex}
deriving (Eq, Show, Read)

addToExtent :: Extent -> Vertex -> Extent
addToExtent ext vert = Extent vertMax vertMin where
(vertMin, vertMax) = (makeCmpVert max (extentMax ext) vert, makeCmpVert min (extentMin ext) vert) where
makeCmpVert f v1 v2 = Vertex(f (vertexX v1) (vertexX v2))
(f (vertexY v1) (vertexY v2))
(f (vertexZ v1) (vertexZ v2))

readCoord :: LBS.ByteString -> Double
readCoord l = case BD.readDouble l of
Nothing -> 0
Just (value, _) -> value

readCoords :: LBS.ByteString -> [Double]
readCoords l | LBS.length l == 0 = []
| otherwise = let coordWords = LBS.split ' ' l
in map readCoord coordWords

parseLine :: LBS.ByteString -> Vertex
parseLine line = Vertex (head coords) (coords!!1) (coords!!2) where
coords = readCoords line

processLines :: [LBS.ByteString] -> Extent -> Extent
processLines strs ext = foldr (\x y -> addToExtent y (parseLine x)) ext strs

processFile :: String -> IO()
processFile name = do
putStrLn name
content <- LBS.readFile name
let (countLine:recordsLines) = LBS.lines content
case LBS.readInt countLine of
Nothing -> putStrLn "Can't read records count"
Just (recordsCount, _) -> do
print recordsCount
let vert = parseLine (head recordsLines)
let ext = Extent vert vert
print $ processLines recordsLines ext

main :: IO()
main = do
args <- getArgs
case args of
[] -> do
putStrLn "Missing file path"
xs -> do
processFile (head xs)
return()

文本文件包含具有三个以空格字符分隔的浮点数的行。该程序总是试图占用计算机上的所有可用内存,并因内存不足错误而崩溃。

最佳答案

你太懒了。 VertexExtent具有非严格字段,并且所有函数都返回 Vertex返回

Vertex thunk1 thunk2

不强制对组件进行评估。还有 addToExtent直接返回一个
Extent thunk1 thunk2

无需评估组件。

因此没有 ByteString s 实际上是提前释放以进行垃圾收集,因为 Double s 还没有从它们中解析出来。

当通过制作 Vertex 的字段来修复时和 Extent严格 - 或返回 Vertex 的函数分别 Extent强制他们输入的所有部分,你的问题是
processLines strs ext = foldr (\x y -> addToExtent y (parseLine x)) ext strs

无法在到达行列表末尾之前开始组装结果,因为那时
(\x y -> addToExtent y (parseLine x))

在其第二个参数中是严格的。

但是,除非 NaN s 和未定义的值,如果我没有遗漏一些东西,如果您使用(严格!)左折叠,结果将是相同的,所以
processLines strs ext = foldl' (\x y -> addToExtent x (parseLine y)) ext strs

如果 Vertex 应该在不保留数据的情况下产生所需的结果和 Extent获取严格的字段。

啊,我确实错过了一些东西:
addToExtent ext vert = Extent vertMax vertMin
where
(vertMin, vertMax) = (makeCmpVert max (extentMax ext) vert, makeCmpVert min (extentMin ext)

如果这不是一个错字(我期望它是),那么修复它会有些困难。

我认为应该是
    (vertMax, vertMin) = ...

关于haskell - 为什么我的 Haskell 程序以内存不足错误结束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15952400/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com