Haskell 是评估还是美元!足以在多线程一元上下文中强制一个值,还是需要pseq?
以下内容似乎有效(例如:它每秒钟都在说Haskell 是评估还是美元!足以在多线程一元上下文中强制一个值,还是需要pseq?,haskell,concurrency,parallel-processing,strictness,Haskell,Concurrency,Parallel Processing,Strictness,以下内容似乎有效(例如:它每秒钟都在说明天肯定会) 然后程序终止 但是,evaluate使用seq。在确定性并行的上下文中,总是强调seq不足以保证实际的计算顺序。这个问题不是在一元上下文中出现的,还是我应该更好地使用它 forkIO $ do let g = last [0..] g `pseq` putMVar godot g 为了确保编译器不能重新排序求值,从而使tryTakeMVar过早成功?如果我没有完全错,那么将最后[0..]求值到WHNF将
明天肯定会)
然后程序终止
但是,evaluate
使用seq
。在确定性并行的上下文中,总是强调seq
不足以保证实际的计算顺序。这个问题不是在一元上下文中出现的,还是我应该更好地使用它
forkIO $ do
let g = last [0..]
g `pseq` putMVar godot g
为了确保编译器不能重新排序求值,从而使tryTakeMVar
过早成功?如果我没有完全错,那么将最后[0..]
求值到WHNF将花费无限长的时间,因为Int
的WHNF意味着您知道确切的数字
putMVar
在last[0..]
被计算到WHNF之前不会开始执行(我们知道这会花费很长时间),因为putMVar
需要调用evaluate
返回的RealWorld
-令牌(s
)。(或者更简单地说:evaluate
有效。它只有在对WHNF的参数求值后才能完成。)
其中,seq#
是一个GHC prim函数,它保证仅在对WHNF计算a
后返回(#a,s#)
(这是它的目的)。也就是说,只有在将a
计算为WHNF后,s
才能用于调用putMVar
。虽然这些标记纯粹是想象的(“现实世界是非常神奇的…”),但它们受到编译器的尊重,整个IO monad都建立在它之上
因此,在这种情况下,evaluate
就足够了evaluate
不仅仅是seq
:它将IO单体测序与seq#
测序相结合以产生其效果
事实上,pseq
版本在我看来有点可疑,因为它最终取决于lazy
,而evaluate
最终取决于seq
和一元令牌传递。我更相信seq#
。pseq
的要点是确保在父线程使用par
触发计算后,它不会立即尝试评估触发的计算本身的结果,而是先执行自己的工作。有关示例,请参见。当您更明确地使用并发时,不需要pseq
forkIO $ do
let g = last [0..]
putMVar godot g
forkIO $ do
let g = last [0..]
g `pseq` putMVar godot g
evaluate :: a -> IO a
evaluate a = IO $ \s -> seq# a s
-- this ^
putMVar (MVar mvar#) x = IO $ \ s# ->
-- which is used here ^^
case putMVar# mvar# x s# of
-- is needed here ^^
s2# -> (# s2#, () #)