Haskell:尝试并行实现“AtomicModifyOref”
据我所知,对Haskell:尝试并行实现“AtomicModifyOref”,haskell,concurrency,ioref,Haskell,Concurrency,Ioref,据我所知,对IORefs的修改非常快,所涉及的只是更新thunk指针。当然,读者(即希望在其网页上看到价值的人)需要花时间来评估这些恶作剧(如果作者没有阅读结果,这些恶作剧可能会增加) 我认为最好开始并行地评估IORef上的修改thunk,因为在许多情况下,它们可能无论如何都必须在某个点上进行评估(显然,这将破坏无限的数据结构) 因此,我编写了以下函数,其签名与atomicModifyIORef类似: atomicModifyIORefPar :: (NFData a) => IORef
IORef
s的修改非常快,所涉及的只是更新thunk指针。当然,读者(即希望在其网页上看到价值的人)需要花时间来评估这些恶作剧(如果作者没有阅读结果,这些恶作剧可能会增加)
我认为最好开始并行地评估IORef
上的修改thunk,因为在许多情况下,它们可能无论如何都必须在某个点上进行评估(显然,这将破坏无限的数据结构)
因此,我编写了以下函数,其签名与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
这可能有效,也可能无效,取决于GHC的版本。火花池与GC的相互作用在历史上一直是可变的。在某些版本中,表达式
force newdata
在atomicModifyIORefPar
返回后没有被范围中的任何内容引用,这意味着在转换par
创建的火花之前,它很可能被垃圾收集,这意味着火花也将被收集
GHC的其他版本将火花池视为GC分析的根源,但这也存在问题。我不记得当前的状态是什么,但我怀疑火花池不算作GC根。它引发的问题(当返回的表达式不引用并行计算的表达式时,并行性损失)比将火花池视为GC根(保留不需要的内存)产生的问题要小
编辑-第二次尝试回答
根据您给出的原因,这个新的实现看起来是正确的。并行计算的表达式也可以从GC根中访问。对我来说很好,但不知何故,当原子性很重要时,我希望使用
MVar
而不是IORef
。您不能定义IORef strict吗?像IORef!Bla@VagifVerdi:在计算修改函数之前,还会锁定IORef
,这难道不会减慢编写程序的速度吗?@vagiverdi否,您只能将严格性注释添加到值构造函数,而不能添加到类型构造函数。并且IORef的值构造函数是隐藏的。(更不用说克林顿的反对了,即使有可能也是有效的。)@VagifVerdi没有。Bla的内容会很严格,但IORef的内容不会很严格。因此,当你在IORef上操作时,你会得到未经评估的指向Bla的Thunk。评估其中一个也会导致同时评估其所有严格的参数,但不是在评估之前。您能对我在上面编辑的问题中提出的解决方案发表意见吗?
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