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% времени, поэтому, хотя я и маленький, я ожидал заметного ускорения, сопоставляя его параллельно.

я протестировал с помощью простой функции

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 здесь? это даже тот случай, когда можно использовать параллелизм?

1 ответов


Я не думаю, что вы измеряете правильно. Ваш parLife действительно немного быстрее, чем life. На самом деле, на моей машине (Phenom X4, 4 core) первое занимает около 92,5% времени, что делает последнее, что, учитывая, что вы говорите, что ожидаете улучшения только на 6%, довольно хорошо.

что настройки бенчмаркинг? Вы пробовали использовать criterion? Вот что я сделал:--7-->

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 ]

составлен с ghc --make -O2 -o bench и побежал с ./bench -o bencht.hmtl +RTS -N3.

вот подробный результат отчета.