我有一个Conway生命游戏的实现。如果可能,我想通过使用并行化来加速它。
life :: [(Int, Int)] -> [(Int, Int)]
life cells = map snd . filter rules . freq $ concatMap neighbours cells
where rules (n, c) = n == 3 || (n == 2 && c `elem` cells)
freq = map (length &&& head) . group . sort
parLife :: [(Int, Int)] -> [(Int, Int)]
parLife cells = parMap rseq snd . filter rules . freq . concat $ parMap rseq neighbours cells
where rules (n, c) = n == 3 || (n == 2 && c `elem` cells)
freq = map (length &&& head) . group . sort
neigbours :: (Int, Int) -> [(Int, Int)]
neighbours (x, y) = [(x + dx, y + dy) | dx <- [-1..1], dy <- [-1..1], dx /= 0 || dy /= 0]
在分析中,邻居占用了6.3%的时间,因此虽然很小,但我预计通过并行映射可以实现明显的加速。我使用了一个简单的函数进行测试。
main = print $ last $ take 200 $ iterate life fPent
where fPent = [(1, 2), (2, 2), (2, 1), (2, 3), (3, 3)]
并编译了并行版本为
ghc --make -O2 -threaded life.hs
并将其运行为
./life +RTS -N3
结果发现并行版本更慢。我在这里使用parMap不正确吗?这种情况是否可以使用并行处理?
freq = map (length &&& head) . group . sort
,所以下一代的cells
总是有序的。 - Daniel Fischer