gpt4 book ai didi

haskell - 我可以利用惰性评估来引用将来的值而不会出现空间泄漏吗?

转载 作者:行者123 更新时间:2023-12-03 16:09:36 26 4
gpt4 key购买 nike

我正在尝试尝试在大量输入上运行一个价格适中的函数,并将该函数的部分输出用作其输入之一。该代码可以按预期运行,但是不幸的是,该过程会占用大量内存(堆上的内存不足22GiB,最大驻留时间刚刚超过1GiB)。这是我的意思的简化示例:

{-# LANGUAGE OverloadedStrings #-}

import Data.List (foldl')
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.IO as TL
import qualified Data.Text.Lazy.Builder as TB

main :: IO ()
main = TL.putStr $ TB.toLazyText showInts

showInts :: TB.Builder
showInts = foldMap fst shownLines
where
shownLines = map (showInt maxwidth) [0..10^7]
maxwidth = foldl' (\n -> max n . snd) 0 shownLines

showInt :: Int -> Int -> (TB.Builder, Int)
showInt maxwidth n = (builder, len)
where
builder = TB.fromText "This number: "
<> TB.fromText (T.replicate (maxwidth - len) " ") <> thisText
<> TB.singleton '\n'
(thisText, len) = expensiveShow n

expensiveShow :: Int -> (TB.Builder, Int)
expensiveShow n = (TB.fromText text, T.length text)
where text = T.pack (show n)
请注意,在 showInts的where子句中, showIntmaxwidth作为参数,其中 maxwidth本身取决于整个列表上正在运行的 showInt maxwidth的输出。
另一方面,如果我天真地将 maxwidth的定义替换为 foldl' max 0 $ map (snd . expensiveShow) [0..10^7],那么最大驻留时间将降至44KiB。我希望,无需预先计算 expensiveShow然后再使用列表 [0..10^7]压缩它,就可以实现这样的性能。
我尝试严格使用该列表(使用 foldl包),但这并没有改善这种情况。
我也想吃蛋糕,也要吃蛋糕:利用懒惰,同时还要使事情变得足够严格,以至于我们不会堆积如山。这可能吗?还是有更好的技术来实现这一目标?

最佳答案

你不能这样做。
问题是您的showInts必须遍历列表两次,首先要找到最长的数字,其次要以必要的格式打印数字。这意味着该列表必须在第一遍和第二遍之间保存在内存中。对于未经评估的重击,这不是问题;只是对整个列表(经过完全评估)进行了两次遍历。
唯一的解决方案是两次生成相同的列表。在这种情况下,这是微不足道的;仅有两个[0..10^7]值,一个为最大长度,另一个为格式化它们。我怀疑在您的实际应用程序中,您正在从文件或其他内容读取它们,在这种情况下,您需要读取两次文件。

关于haskell - 我可以利用惰性评估来引用将来的值而不会出现空间泄漏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66563595/

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