2012-09-01 7 views
9

Conway'in Yaşam Oyununun bir uygulamasına sahibim. Paralelizm kullanarak mümkünse hızlandırmak istiyorum. Ben paralel bir şekilde eşleyerek farkedilir bir hızlanma beklenen küçük iken böylece profilleme içindeHaskell parMap ve paralellik

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] 

, komşular, harcanan zamanın% 6.3 oluşturuyor.

ben basit işlevi

main = print $ last $ take 200 $ iterate life fPent 
    where fPent = [(1, 2), (2, 2), (2, 1), (2, 3), (3, 3)] 

ile test edilmiş ve

ghc --make -O2 -threaded life.hs 

gibi paralel sürümü derlenmiş ve

./life +RTS -N3 

paralel versiyonu daha yavaş olduğu ortaya çıktı olarak ran . ParMap'i yanlış mı kullanıyorum? Bu, paralelliğin kullanılabileceği bir durum mu?

+0

Öncelikle, bilgisayarınızda en az 3 çekirdek var mı? İkinci olarak, paralellik her zaman bazı yüklerle birlikte gelir, bu yüzden her bir iş parçacığı tarafından yapılan iş çok küçükse, ekstra yük herhangi bir hız artışından ağır basacaktır. – huon

+0

i bir i5-2500K var, yani parallelising gelen daha algoritma geliştirilmesi dan çok daha büyük kat hızlanma alabilirsiniz – cdk

+0

Not avaliable kesinlikle 4 çekirdeğe kadar yoktur. Zamanın büyük kısmı "sort" ve "elem" de harcanır. Hücre listesinin sıralandığı (ve fPent'in değiştirildiği şekilde değiştirildiği) gerçeğini kullanarak, bu süreyi kabaca yarıya düşürebilirsiniz. –

cevap

2

Haklı ölçme sanmıyorum. parLife, gerçekten life'dan biraz daha hızlı. Aslında, makinemde (Phenom X4, 4 çekirdekli), sadece, sadece% 6'lık bir iyileşme beklediğinizi düşündüğünüzü düşünürsek, bunun sadece% 92.5'ini alır. senin kıyaslama kurulum ne

mı? criterion kullanmayı denediniz mi? İşte ne yaptım:

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 ile Derleyen ve ./bench -o bencht.hmtl +RTS -N3 ile koştu.

Here's the detailed result of the report.

+0

Hmm, garip. Ayrıca “parLife” in kriterden daha hızlı sonuç almasını sağlıyorum, ama bağımsız bir şeyi çalıştırdığımda, “parLife” sürekli olarak “life” den daha yavaş. –

+0

Ah, yalnızca dişli çalışma süresiyle, iş parçacığı ile değil! –

+0

Sanırım sürecin uzun ömürlü olmasıyla ilgili bir şey var… iş parçacığı havuzu vb. başlatılıyor, paralelleştirmekten aldığımız kazançlardan daha pahalı. –