cdk*_*cdk 9 parallel-processing haskell conways-game-of-life
我实现了康威的生命游戏.我希望通过使用并行性来加速它.
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]
Run Code Online (Sandbox Code Playgroud)
在分析中,邻居占用了花费的时间的6.3%,所以虽然很小,但我希望通过并行映射来获得显着的加速.
我测试了一个简单的功能
main = print $ last $ take 200 $ iterate life fPent
where fPent = [(1, 2), (2, 2), (2, 1), (2, 3), (3, 3)]
Run Code Online (Sandbox Code Playgroud)
并将并行版本编译为
ghc --make -O2 -threaded life.hs
Run Code Online (Sandbox Code Playgroud)
然后把它作为
./life +RTS -N3
Run Code Online (Sandbox Code Playgroud)
事实证明,并行版本更慢.我在这里错误地使用parMap吗?这甚至是可以使用并行性的情况吗?
我认为你的测量方法不对。你的parLife速度确实比 快一点life。事实上,在我的机器(Phenom X4,4 核)上,前者只花费后者大约 92.5% 的时间,考虑到您说您预计只有 6% 的改进,这已经相当不错了。
您的基准测试设置是什么?你尝试过使用criterion吗?这就是我所做的:
import Criterion
import Criterion.Main
-- your code, minus main
runGame f n = last $ take n $ iterate f fPent
where fPent = [(1, 2), (2, 2), (2, 1), (2, 3), (3, 3)]
main = defaultMain
[ bench "No parallelism 200" $ whnf (runGame life) 200
, bench "Parallelism 200" $ whnf (runGame parLife) 200 ]
Run Code Online (Sandbox Code Playgroud)
编译ghc --make -O2 -o bench并运行./bench -o bencht.hmtl +RTS -N3。