Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 使用Haskell';s MVar软件包,但严格遵守seq_Multithreading_Haskell - Fatal编程技术网

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')