Haskell 并行最大值计算
我有一组问题,我想同时进行评估。这些问题使用一个简单的表达式类型表示,非常类似于:Haskell 并行最大值计算,haskell,parallel-processing,Haskell,Parallel Processing,我有一组问题,我想同时进行评估。这些问题使用一个简单的表达式类型表示,非常类似于: -- Expressions are either a constant value or two expressions -- combined using a certain operation data Expr = Const NumType | Binary BinOp Expr Expr -- The possible operations data BinOp = Add | S
-- Expressions are either a constant value or two expressions
-- combined using a certain operation
data Expr
= Const NumType
| Binary BinOp Expr Expr
-- The possible operations
data BinOp = Add | Sub | Mul | Div
deriving (Eq)
这些表达式是动态构建的,计算结果可能有效,也可能无效。当遇到无效结果时,它被表示为停止计算的monad
data Result a
= Val { val :: a }
| Exc { exc :: String }
instance Monad Result where
return = Val
(Exc e) >>= _ = (Exc e)
(Val v) >>= g = g v
要确定每个已解决问题的值,我有两个相关函数:
eval :: Expr -> Result NumType
score :: Expr -> NumType
最后,我有一些solve函数,它们将返回一个[Expr]
。这导致我目前的主要功能如下:
main :: IO ()
main = do
strAvailableNumbers <- getLine
strTargetNumber <- getLine
let numbers = parseList strAvailableNumbers
target = parseTargetNumber strTargetNumber in
sequence $ map (print) $
solveHeuristic1 (Problem target numbers) [Add] [Sub] ++
solveHeuristic2 (Problem target numbers)
return ()
main::IO()
main=do
strAvailableNumbers这里的问题是,使用seq
评估IO
操作几乎没有任何作用。因此,您只是以稍微高一点的开销按顺序运行
你可以折射物体,使其再次纯净
main :: IO ()
main = do
mapM_ (`seq` print "found it") -- make sure we're not
-- benchmarking printing stuff
. concat
. parMap rdeepseq (solve [1..10000000])
$ [42, 42]
return ()
并添加NFData
的实例以使用rdeepseq
,这将全面评估事物
instance NFData BinOp -- Binop is just an enum, WHNF = NF
instance NFData Expr where
rnf (Const a) = a `deepseq` ()
rnf (Binary b e1 e2) = b `deepseq` e1 `deepseq` e2 `deepseq` ()
现在如果我们运行它,我们会得到。。。堆垛机溢出。我增加了足够的大小,以便我们进行搜索,以使它花费足够长的时间来进行基准测试,现在将这两个结构完全加载到内存中将使堆栈崩溃。使用-N2
时,如果将堆栈大小增加到不破坏所有内容的程度,则运行速度将提高40%(3秒对5秒)。我会考虑预期的结果。在运行这个程序时,我可以看到2个内核短暂地跃升到100%
最终编译顺序
> ghc -O2 -threaded -rtsops bench.hs
> ./bench +RTS -K10000000 -N2
使用rdeepseq
而不是rseq
会有什么不同吗?这给了我一个使用
rdeepseq``而产生的(NFData(IO())实例。你介意发布所有代码吗(可能在链接中?)我有一个想法,但我想测试一下first@MarcusRiemer嗯,你在哪里使用rseq
?我在问题中给出的代码中没有看到它。如果你想并行运行IO
,也许你想要的是async
包。@jozefg:我上传了一个相当粗糙的版本到。