繁体   English   中英

Haskell:尝试并行`atomicModifyIORef`实现

[英]Haskell: Attempt at parallel `atomicModifyIORef` implementation

根据我的理解,对IORef的修改非常快,所有它们都涉及更新thunk指针。 当然,读者(即想要在他们的网页上看到价值的人)将需要花时间来评估这些thunk(如果作者没有回读结果,这可能会积累)。

我认为开始实际上并行地评估IORef上的修改IORef是好的,因为在许多情况下它们可能必须在某个时候进行评估(显然,这将打破无限的数据结构)。

所以我编写了以下函数,与atomicModifyIORef具有类似的签名:

atomicModifyIORefPar :: (NFData a) => IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORefPar ioref f =
  let 
    g olddata = 
      let (newdata, result) = f olddata in (newdata, (result, newdata))
  in do
    (result, newdata) <- atomicModifyIORef ioref g
    force newdata `par` return result

这似乎工作( 测试代码在这里 )。 我在这里做错了什么吗? 或者有更好的方法吗?


编辑:第二次尝试

灵感来自Carl的答案如下 我们实际存储force newdataIORef 这与newdata完全相同,但是显示了我们想要为以后保持force newdata的运行时,所以它不会垃圾收集火花。

atomicModifyIORefPar :: (NFData a) => IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORefPar ioref f =
  let 
    g olddata = 
      let 
        (newdata, result) = f olddata
        newdata_forced = force newdata
      in 
        (newdata_forced, (result, newdata_forced))
  in do
    (result, newdata_forced) <- atomicModifyIORef ioref g
    newdata_forced `par` return result

根据GHC的版本,这可能有效,也可能无效。 火花池与GC的相互作用在整个历史中都是可变的。 在某些版本中,在atomicModifyIORefPar返回之后,范围内的任何东西都没有引用表达式force newdata的事实意味着它可能会在par之前创建的spark被转换之前被垃圾收集,这意味着火花也将被收集。

其他版本的GHC已将火花池视为GC分析的根源,但这也存在问题。 我不记得当前状态是什么,但我怀疑它是火花池不算作GC的根源。 它引发的问题(当返回的表达式不引用并行计算的表达式时失去并行性)比将Spark池视为GC根(保留不需要的内存)所产生的问题要糟糕得多。


编辑 - 第二次尝试回答

由于您给出的原因,这个新的实现看起来正确。 并行计算的表达式也可以从GC根源到达。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM