私はConwayのGame of Lifeを実装しています。私は、並列性を使用することによって可能な限り高速化したいと思います。プロファイリングで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]
小さなI並列にそれをマッピングすることにより、顕著な高速化を期待しつつ、隣人は、費やされる時間の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を間違って使用していますか?これは並列処理が使用できる場合でもそうですか?
まず、コンピュータに少なくとも3つのコアがありますか?第2に、並列処理には常にオーバーヘッドが発生するため、各スレッドで実行される作業が非常に小さい場合、余分なオーバーヘッドがすべてのスピードアップよりも重要です。 – huon
私はi5-2500kを持っていますので、最大4つのコアが利用可能です。 – cdk
並列化よりもアルゴリズムの改善からはるかに高速化できます。大部分の時間は 'sort'と' elem'で費やされます。セルのリストがソートされている(そしてソートされるように 'fPent'を変更するという事実を利用して)、あなたはおおよそ時間を半分にすることができます。 –