haskell - 在 Haskell 中编写类似信号量的代码的最佳方法是什么?

标签 haskell concurrency parallel-processing

假设我有一个函数f,它接受一个整数参数。 f 可能不会因某些参数而终止,但其结果同样有值(value)。 (具体来说,参数可以是随机数生成器的种子,它被传递给 SAT 求解器。)

我想使用并发并调用 f 1f 2f 3 等,并在第一个完成时返回。因此,每个线程都应该运行如下所示的代码

comp <- start_proc (f 1)
wait(comp || anyDone) -- wait for _either_ of these signals to be true
if comp then
    set anyDone = True

最简单的方法是什么?我想到了 AMB 运算符,但我需要同时运行所有进程(例如在 24 或 80 核机器上)。 (分布式计算解决方案会更好。)粗略地看一下 AMB wiki page表明它可能不支持非终止进程?

测试

目前,我还没有得到我想要的答案。我认为这可能更多是我如何创建流程的问题,而不是其他问题。

定义

runProc (x:xs) =
    createProcess (proc x xs) >>= \(_, _, _, h) -> waitForProcess h

然后,我想对 runProc ["zsh", "-c", "sleep 3"]runProc ["ls"] 进行竞赛。我稍微修改了托马斯的答案,但没有成功。

raceL :: [IO α] -> IO α
raceL ops = do
    mv <- newEmptyMVar
    tids <- forM ops (\op -> forkIO (op >>= putMVar mv))
    answer <- takeMVar mv
    mapM_ killThread tids
    return answer

使用-threaded编译并使用+RTS -N运行(我有一台4核机器)似乎没有帮助。

最佳答案

为什么不只是一个 MVarforkIO

import Control.Concurrent
import Control.Concurrent.MVar
import System.Environment
import Control.Monad

main = do
  mv <- newEmptyMVar
  [nrThreads] <- liftM (map read) getArgs
  tids <- replicateM nrThreads (forkIO $ operation mv)
  answer <- takeMVar mv
  mapM_ killThread tids

operation :: MVar Int -> IO ()
operation mv = putMVar mv 5

这将 fork nrThreads个轻量级线程。一旦一个线程完成,它应该将答案放入提供的 MVar 中。然后所有其他线程将被主线程杀死。不需要显式轮询,因为一旦 MVar 变为非空,GHC RTS 将重新安排 main

关于haskell - 在 Haskell 中编写类似信号量的代码的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7216149/

相关文章:

haskell - 有人可以解释这个懒惰的斐波那契解决方案吗?

haskell - monad 中的纯映射

java - 当不同的线程访问一个静态方法时,在该方法中声明的对象是本地的还是在java中共享的

haskell - 用于功能并行的编程语言 : F# vs Haskell

sql - 如何优化Spark sql以并行运行

Haskell 按列表索引过滤

haskell - 为什么 mconcat 需要一个列表而不是一个可折叠的?

python - 我可以在 Future 中使用 ProcessPoolExecutor 吗?

c++ - 了解 tbb::parallel_reduce 的并发性

concurrency - 通知所有 goroutines