Multithreading 使用Haskell';s MVar软件包,但严格遵守seq
在Multithreading 使用Haskell';s MVar软件包,但严格遵守seq,multithreading,haskell,Multithreading,Haskell,在Control.Concurrent.MVar关于黑客攻击的文档中,我们对MVars的使用有一个“了解”。这是我的建议 MVar表示,当您使用putMVar将某个东西放入MVar时,如果您放入的东西是一个巨大的撞击,那么接收线程将有一个混乱的评估工作,而不是发送线程 除了可能令人讨厌或毫无根据之外,为了纠正这种情况,它将我们引向了evaluate的方向,它本身说要使用seq。大家最喜欢的haskell函数 的语义应该是这样的: 所以我的问题是:为什么不在分叉线程中计算呢 concTreeMap
Control.Concurrent.MVar
关于黑客攻击的文档中,我们对MVar
s的使用有一个“了解”。这是我的建议
MVar表示,当您使用putMVar
将某个东西放入MVar
时,如果您放入的东西是一个巨大的撞击,那么接收线程将有一个混乱的评估工作,而不是发送线程
除了可能令人讨厌或毫无根据之外,为了纠正这种情况,它将我们引向了evaluate
的方向,它本身说要使用seq
。大家最喜欢的haskell函数
的语义应该是这样的:
所以我的问题是:为什么不在分叉线程中计算呢
concTreeMap :: (a -> b) -> BinaryTree a -> IO (BinaryTree b)
concTreeMap f Leaf = return Leaf
concTreeMap f (Branch v l r) = do
res <- newEmptyMVar
forkIO $ do
let fv = f v
evaluate fv `seq` (putMVar res fv)
v' <- takeMVar res
l' <- concTreeMap f l
r' <- concTreeMap f r
return (Branch v' l' r')
concTreeMap::(a->b)->二进制树a->IO(二进制树b)
contreemap f叶=返回叶
混凝土映射f(分支v l r)=do
res二进制树a->IO(二进制树b)
contreemap f叶=返回叶
混凝土映射f(分支v l r)=do
res因为您使用seq
强制计算evaluate fv
。这是一个IO
操作,评估它与运行它完全不同
如果你把一个IO
动作想象成一个配方,对它运行seq
,对它进行评估,只是确保配方被完全写下来,但运行实际上是在使用配方来生产一些东西
应更换分叉部分
forkIO $ do
let fv = f v
evaluate fv
putMVar res fv
假设您按照Petr Pudlák的答案修复了程序,那么您将尝试在启动线程后立即从MVar
中获取一个值。因此,您没有并行性,因为运行contreemap
的线程必须等待MVar
满,这意味着等待分叉线程将fv
放入MVar
中,直到对其求值之后才会这样做。同时,原始线程什么也不做
你不是想写信吗
...
forkIO $ do
let fv = f v
evaluate fv `seq` (putMVar res fv)
l' <- concTreeMap f l
r' <- concTreeMap f r
v' <- takeMVar res -- Note: this moved to after we do more work
return (Branch v' l' r')
。。。
forkIO$do
设fv=fv
评估fv`seq`(putMVar res fv)
我知道你在说什么,但这比不同时做还要慢。我也觉得你可能没有足够的信息来诊断这个问题,虽然。。。Hmm@lol你如何测量速度?您的f
有多复杂?您确定并发性被忽略了吗(使用MVar
s切换CPU上下文不会比并行化带来的收益更大?f
是一个阶乘函数,我用time
对其进行计时,对于曾经在这里使用过的谷歌用户,记住在您的应用程序中使用ghc-threaded
进行编译,控制O1
,O2
,等等。)tests@lol听起来不错d、 比时间更精确的测量方法是由提供的。你引用的等式确切地说,evaluate`seq`y
与y
是一样的,也就是说,你使用evaluate
没有任何作用。你是一个活生生的传奇。现在我该如何兑现你们两人的积分哈哈?!?!?
forkIO $ do
let fv = f v
evaluate fv
putMVar res fv
...
forkIO $ do
let fv = f v
evaluate fv `seq` (putMVar res fv)
l' <- concTreeMap f l
r' <- concTreeMap f r
v' <- takeMVar res -- Note: this moved to after we do more work
return (Branch v' l' r')