gpt4 book ai didi

multithreading - 强制跨 IORef : rnf, deepSeq 或其他东西进行评估?

转载 作者:行者123 更新时间:2023-12-04 06:46:28 26 4
gpt4 key购买 nike

我有一个长期运行的进程,它是 forkIO 'd,它产生像素颜色值:

takesAgesToRun :: [[Color]]

myForkedProcess :: IORef [[Color]] -> IO ()
myForkedProcess ref = do let colors = takesAgesToRun
writeIORef ref colors

(其中 Color 仅包含三个 Double 值)。

正如预期的那样,当在 IORef 的“另一边”阅读时,存储的值只是一个 thunk,因此会阻塞主进程。

我知道我需要全面评估 [[Color]]值(value)到头正常形式,但似乎有两种方法可以实现这一点,而且,我不确定如何将其中任何一种合并到我的代码中。

我该怎么办?我是否使用 rnf , deepSeq ,或其他一些线程策略? 其中之一是首选的,而其他的是否已弃用?它如何适合我的代码?

(PS 请忽略将图像存储为颜色列表列表是愚蠢的这一事实 - 这只是代码的简化版本)。

最佳答案

使用 deepSeq .它就像 seq 一样使用.你会像这样合并它:

myForkedProcess :: IORef [[Color]] -> IO ()
myForkedProcess ref = do let colors = takesAgesToRun
deepSeq colors $ writeIORef ref colors

这将强制在“writeIORef”调用之前完全评估“颜色”。

为了使其工作,您需要一个 NFData Color 的实例.具体如何写取决于颜色的定义,但这里有两个例子:
-- just for reference
data Color = Color Double Double Double

instance NFData Color where
rnf (Color r g b) = r `seq` g `seq` b `seq` ()

-- closer to the likely actual implementation for Color
data Color2 = Color2 !Double !Double !Double

instance NFData Color2 where
-- the default implementation is fine

对于 Color例如,您需要确保颜色的所有组件在 Color 是时都被完全评估 [1]。这就是 seq做。我们可以使用 seq而不是 deepSeq在这里是因为我们知道每个组件都是一个 Double ,因此完全由 seq 评估。如果组件是更复杂的数据类型,那么我们需要使用 deepSeq写入 NFData 实例时。

Color2它更简单一些。由于 bang 模式,我们知道组件在 Color2 时被完全评估。是。这意味着我们可以使用默认实现,它计算 Color2到弱头部范式,由于刘海模式,它被充分评估。
rnf与 Control.Parallel.Strategies 结合使用时主要有用。这是 deepSeq 的当前定义
deepseq :: NFData a => a -> b -> b
deepseq a b = rnf a `seq` b

deepseq所做的就是调用 rnf并保证其输出 () 被评估。这真的是唯一的使用方法 rnf直接地。

[1] Haskell 只提供了两种评估东西的通用方法:模式匹配和 seq .其他一切都建立在其中之一或两者之上。对于 NFData Color 实例, Color首先通过与 Color 的模式匹配评估为 WHNF构造函数,然后通过 seq 评估组件。

当然,还有第三种高度特化的评估方法:即函数 main :: IO ()将被执行以评估 () .

关于multithreading - 强制跨 IORef : rnf, deepSeq 或其他东西进行评估?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6662543/

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