2012-09-01 7 views
9

मेरे पास Conway's 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] 
रूपरेखा में

, पड़ोसियों, समय बिताया के 6.3% के लिए खातों इसलिए जब छोटे मैं समानांतर में यह मैप करके एक उल्लेखनीय speedup की उम्मीद।

मैं एक साधारण समारोह

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 

यह पता चला है समानांतर संस्करण धीमी है कि के रूप में यह भाग गया । क्या मैं यहाँ गलत तरीके से पैरामैप का उपयोग कर रहा हूं? क्या यह एक ऐसा मामला भी है जहां समांतरता का उपयोग किया जा सकता है?

+0

सबसे पहले, क्या आपके कंप्यूटर में कम से कम 3 कोर हैं? दूसरा, समांतरता हमेशा कुछ ओवरहेड के साथ आता है, इसलिए यदि प्रत्येक थ्रेड द्वारा किया जा रहा काम बहुत छोटा है, तो अतिरिक्त ओवरहेड किसी भी गति-अप से अधिक होगा। – huon

+0

मेरे पास i5-2500k है, इसलिए निश्चित रूप से 4 कोर तक उपलब्ध हैं – cdk

+0

ध्यान दें कि आप समांतरता से एल्गोरिदम में सुधार करने से बहुत अधिक गतिशीलता प्राप्त कर सकते हैं। समय का बड़ा हिस्सा 'क्रम' और 'elem' में बिताया जाता है। इस तथ्य का उपयोग करना कि कोशिकाओं की सूची को क्रमबद्ध किया गया है (और 'fPent' को बदलना ताकि इसे क्रमबद्ध किया जा सके) आप मोटे तौर पर समय को कम कर सकते हैं। –

उत्तर

2

मुझे नहीं लगता कि आप सही माप रहे हैं। आपका parLife वास्तव में life से थोड़ा तेज़ है। असल में, मेरी मशीन (फेनोम एक्स 4, 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 ] 

ghc --make -O2 -o bench साथ संकलित और ./bench -o bencht.hmtl +RTS -N3 साथ भाग गया।

Here's the detailed result of the report

+0

हम्म, अजीब। मुझे यह भी परिणाम मिलता है कि 'parLife' मानदंड से तेज़ है, लेकिन जब मैं चीज़ स्टैंडअलोन चलाता हूं,' parLife' लगातार 'जीवन' से काफी धीमी है। –

+0

आह, केवल थ्रेडेड रनटाइम के साथ, नॉनथ्रेडेड के साथ नहीं! –

+0

मुझे लगता है कि इस प्रक्रिया की दीर्घायु के साथ कुछ करना है ... आईई। थ्रेड पूल इत्यादि को प्रारंभ करना (स्वीकार्य रूप से नाबालिग) लाभों की तुलना में अधिक महंगा है जो हम समांतरता से प्राप्त करते हैं। संभवतः –