【问题标题】:Haskell concurrency - is forkIO really nondeterministic?Haskell 并发 - forkIO 真的是不确定的吗?
【发布时间】:2012-04-20 13:47:23
【问题描述】:

我正在尝试在 Haskell 中使用并发进行特定优化,其中只需要两个值中的一个,并且根据具体情况,创建其中一个值可能比另一个快得多。

我想我可以只用 forkIO 运行 2 个线程,然后等到一个值放入 M​​Var。这是我为此编写的一个简单测试:

import Control.Concurrent

main = do out <- newEmptyMVar
          t1 <- forkIO (makeString out)
          t2 <- forkIO (makeInt out)
          v <- takeMVar out
          killThread t1
          killThread t2
          case v of
               Left s -> putStrLn s
               Right i -> putStrLn $ show i

makeString out = do s <- return ( show (primes !! 10000))
                    putMVar out $ Left s

makeInt out = do i <- return 2
                 putMVar out $ Right i

primes = sieve [2..] 
 where sieve (x:xs) = x : (sieve $ filter ((/=0).(flip mod x)) xs)

编译:

ghc --make -threaded Test

然而,只有 Left 的情况下,虽然获得质数应该需要足够长的时间来启动 makeInt 线程(并且 return 2 真的不应该花费那么多时间)。为什么会这样,我该如何解决?

【问题讨论】:

  • 你如何运行你的代码?默认情况下,haskell 使用轻线程而不是真正的操作系统线程。我不知道细节,但这可能会改变很多调度策略。
  • 可能不适合您的情况,但您也可能会研究一些关于“推测并行性”的工作:hackage.haskell.org/package/speculation
  • 仅供参考,hackage.haskell.org/package/monad-par 公开了一个相当不错的、外部纯并行 API,但仍允许您明确声明分叉、连接等。

标签: haskell concurrency


【解决方案1】:

这里的问题是懒惰。 makeString 只是插入一个 thunk 来计算 show (primes !! 10000),然后由主线程评估。插入 thunk 非常快,所以在这种情况下它恰好赢得了比赛。

要强制在线程内进行评估,您可以将return 更改为evaluate

makeString out = do s <- evaluate $ show (primes !! 10000)
                    putMVar out $ Left s

这应该会导致makeInt 在大多数情况下赢得比赛(尽管不能保证)。

【讨论】:

  • 谢谢!我完全忘了考虑懒惰。
【解决方案2】:

是的,线程确实是不确定的(在 GHC 中)。

碰巧您的特定代码的结构和优化方式使 t1 始终获胜。没有任何保证。

如果您想尝试对其进行按摩以产生不同的结果,请尝试打开优化 (-O2) 和/或使用多核 (+RTS -N)。

例如在我的机器上,连续运行两次:

$ ghc -O2 -threaded --make A.hs -rtsopts -fforce-recomp
[1 of 1] Compiling Main             ( A.hs, A.o )
Linking A.exe ...
$ ./A +RTS -N2
2
$ ./A +RTS -N2
104743

正如 hammar 指出的那样,您还可以构建代码以强制在线程中进行更多工作(或切换到 using strict mvars)。

【讨论】:

  • 谢谢 - 我什至不知道我可以将参数传递给 RTS。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
  • 2015-02-23
  • 2011-05-07
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
  • 2012-05-16
相关资源
最近更新 更多