我有一个Conway的生命游戏的实现。如果可能的话,我想通过使用并行性来加速它。Haskell parMap和并行性
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%,因此,虽然小我期望的noticable加速通过并联映射它。
我用一个简单的函数
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吗?这是甚至可以使用并行性的情况吗?
首先,你的计算机至少有3个内核?其次,并行性总是会带来一些开销,所以如果每个线程所做的工作都非常小,额外的开销将超过任何加速。 – huon
我有一个i5-2500k,所以肯定有多达4个内核可用 – cdk
请注意,您可以从改进算法中获得比并行化更大的加速。大部分时间都花在'sort'和'elem'上。使用单元格列表进行排序(并更改'fPent'以便对它进行排序)这一事实,可以大致减半时间。 –