在Haskell中使用并行策略时减速

时间:2012-04-04 10:31:32

标签: haskell parallel-processing

我正在研究Andre Loh在haskell练习中确定性并行编程的练习。我试图通过使用策略将N-Queens顺序代码转换为并行,但是我注意到并行代码比顺序代码运行得慢得多,而且堆栈空间不足也会出错。

这是并行N-Queens的代码,

import Control.Monad
import System.Environment
import GHC.Conc
import Control.Parallel.Strategies
import Data.List
import Data.Function

type PartialSolution = [Int] -- per column, list the row the queen is in
type Solution = PartialSolution

type BoardSize = Int

chunk :: Int -> [a] -> [[a]]
chunk n [] = []
chunk n xs = case splitAt n xs of
         (ys, zs) -> ys : chunk n zs

-- Generate all solutions for a given board size.
queens :: BoardSize -> [Solution]
--queens n = iterate (concatMap (addQueen n)) [[]] !! n
queens n = iterate (\l -> concat (map (addQueen n) l `using` parListChunk (n `div`            numCapabilities) rdeepseq)) [[]] !! n


-- Given the size of the problem and a partial solution for the
-- first few columns, find all possible assignments for the next
-- column and extend the partial solution.
addQueen :: BoardSize -> PartialSolution -> [PartialSolution]
addQueen n s = [ x : s | x <- [1..n], safe x s 1 ]

-- Given a row number, a partial solution and an offset, check
-- that a queen placed at that row threatens no queen in the
-- partial solution.
safe :: Int -> PartialSolution -> Int -> Bool
safe x []    n = True
safe x (c:y) n = x /= c && x /= c + n && x /= c - n && safe x y (n + 1)

main = do
        [n] <- getArgs
        print $ length $ queens (read n)

(\l -> concat (map (addQueen n) l using parListChunk (n div numCapabilities) rdeepseq))是我从原始代码更改的内容。我见过Simon Marlow的解决方案,但我想知道代码中减速和错误的原因。

提前致谢。

1 个答案:

答案 0 :(得分:4)

你正在激发太多的工作。 parListChunk的{​​{1}}参数可能是您系统中的7,(2个内核,n = 14运行)。这个列表会很快变大,所以没有必要引发这么小的工作单元(我不明白为什么将它与div n numCapabilities的价值联系起来是有意义的。)

如果我添加十倍因子(在这种情况下制作火花单元70),那么我在单线程上获得明显的性能胜利。此外,我没有您提到的堆栈问题 - 如果它更改了您的n值,那么我会将其报告为错误。

如果我每800分钟进行一次分组,那么时间最终分别为5.375秒和7.9秒。超过800,性能开始再次恶化,ymmv。

编辑:

parListChunk