2013-01-31 7 views
15

मैं समानांतर रणनीतियों के आसपास अपने सिर को लपेटने की कोशिश कर रहा हूं। मुझे लगता है कि मैं समझता हूं कि प्रत्येक संयोजक क्या करता है, लेकिन हर बार जब मैं उन्हें 1 से अधिक कोर के साथ उपयोग करने का प्रयास करता हूं, तो कार्यक्रम काफी धीमा हो जाता है।कुशल समानांतर रणनीतियों

उदाहरण के लिए थोड़ी देर पहले मैंने ~ 700 दस्तावेजों से हिस्टोग्राम (और उनके अद्वितीय शब्दों) की गणना करने की कोशिश की। मैंने सोचा कि फ़ाइल स्तर ग्रैन्युलरिटी का उपयोग करना ठीक रहेगा। -N4 के साथ मुझे 1.70 कार्य संतुलन मिलता है। हालांकि -N1 के साथ यह -N4 के साथ आधे समय में चलता है। मुझे यकीन नहीं है कि सवाल वास्तव में क्या है, लेकिन मैं यह जानना चाहता हूं कि कैसे तय करें/कब/कैसे समानांतरता और इसे समझने के लिए। यह समानांतर कैसे होगा ताकि गति घटने के बजाय कोर के साथ बढ़ जाती है?

import Data.Map (Map) 
import qualified Data.Map as M 
import System.Directory 
import Control.Applicative 
import Data.Vector (Vector) 
import qualified Data.Vector as V 
import qualified Data.Text as T 
import qualified Data.Text.IO as TI 
import Data.Text (Text) 
import System.FilePath ((</>)) 
import Control.Parallel.Strategies 
import qualified Data.Set as S 
import Data.Set (Set) 
import GHC.Conc (pseq, numCapabilities) 
import Data.List (foldl') 

mapReduce stratm m stratr r xs = let 
    mapped = parMap stratm m xs 
    reduced = r mapped `using` stratr 
    in mapped `pseq` reduced 

type Histogram = Map Text Int 

rootDir = "/home/masse/Documents/text_conversion/" 

finnishStop = ["minä", "sinä", "hän", "kuitenkin", "jälkeen", "mukaanlukien", "koska", "mutta", "jos", "kuitenkin", "kun", "kunnes", "sanoo", "sanoi", "sanoa", "miksi", "vielä", "sinun"] 
englishStop = ["a","able","about","across","after","all","almost","also","am","among","an","and","any","are","as","at","be","because","been","but","by","can","cannot","could","dear","did","do","does","either","else","ever","every","for","from","get","got","had","has","have","he","her","hers","him","his","how","however","i","if","in","into","is","it","its","just","least","let","like","likely","may","me","might","most","must","my","neither","no","nor","not","of","off","often","on","only","or","other","our","own","rather","said","say","says","she","should","since","so","some","than","that","the","their","them","then","there","these","they","this","tis","to","too","twas","us","wants","was","we","were","what","when","where","which","while","who","whom","why","will","with","would","yet","you","your"] 
isStopWord :: Text -> Bool 
isStopWord x = x `elem` (finnishStop ++ englishStop) 

textFiles :: IO [FilePath] 
textFiles = map (rootDir </>) . filter (not . meta) <$> getDirectoryContents rootDir 
    where meta "." = True 
     meta ".." = True 
     meta _ = False 

histogram :: Text -> Histogram 
histogram = foldr (\k -> M.insertWith' (+) k 1) M.empty . filter (not . isStopWord) . T.words 

wordList = do 
    files <- mapM TI.readFile =<< textFiles 
    return $ mapReduce rseq histogram rseq reduce files 
    where 
    reduce = M.unions 

main = do 
    list <- wordList 
    print $ M.size list 

pdfs पाठ फ़ाइलों के लिए के रूप में, मैं उपयोग कर रहा हूँ पाठ फ़ाइलों के लिए तो मैं उन्हें प्रदान नहीं कर सकते परिवर्तित, लेकिन इस प्रयोजन के लिए, लगभग किसी भी पुस्तक/प्रोजेक्ट गुटेनबर्ग से किताबें करना चाहिए।

संपादित: स्क्रिप्ट

+1

'हिस्टोग्राम = फ़ोल्डर (\ के -> एम .insertWith '(+) के 1) एम .empty। फ़िल्टर (नहीं। istoptop)। T.words' को 'फ़ोल्ड' का उपयोग करना चाहिए। 'फ़ोल्डर' गहराई से एक गड़बड़ी बनाता है क्योंकि सूची 'मानचित्र' बनाने से पहले बहुत लंबी है। –

+3

यदि आप एक छोटा और पूरा उदाहरण प्रदान करेंगे तो ऐसे प्रश्न का उत्तर देना बहुत आसान होगा। अधिक विस्तार से देखे बिना: क्या आप सुनिश्चित हैं कि 'rseq'' mapReduce' के पहले तर्क के रूप में पर्याप्त है कि काम का प्रत्येक हिस्सा वास्तव में समानांतर में किया जाता है? समानांतर कार्यों की अच्छी ग्रैन्युलरिटी सुनिश्चित करने के लिए पर्याप्त 'पैरामैप' में प्रति सूची तत्व के अनुसार काम की मात्रा कितनी बड़ी है? क्या आपने प्रत्येक कार्यक्रम पर क्या चल रहा है यह देखने के लिए अपने प्रोग्राम पर थ्रेडस्कोप चलाने की कोशिश की है? क्या आपने कचरा संग्रहण में कितना समय व्यतीत किया है, यह देखने के लिए आपने '+ आरटीएस-एस 'के साथ दौड़ने की कोशिश की है? – kosmikus

+0

कोसमिकस, आपका पूरा उदाहरण किस प्रकार का है? आयात के अलावा कि स्क्रिप्ट पूरी तरह से चलाने योग्य है। आरएसईसी/rdeepseq के लिए, मैं किसी भी भाग्य के साथ अन्य संयोजनों के साथ कोशिश की। पैरामैप के लिए, मैंने parListChunk और parListN के साथ मानचित्र का भी प्रयास किया। और थ्रेस्स्कोप के लिए, कार्रवाई और जीसी दोनों तेजी से लग रहा था। - ने कहा कि यह 60% कार्य समय था, जो -एन 1 मामले से बेहतर था। – Masse

उत्तर

4

प्रैक्टिस में, समानांतर संयोजन करने वाले समानांतर संयोजक प्राप्त करना मुश्किल हो सकता है। अन्य लोगों ने यह सुनिश्चित करने के लिए अपना कोड अधिक सख्त बनाने का उल्लेख किया है कि आप वास्तव में समानांतर में काम कर रहे हैं, जो निश्चित रूप से महत्वपूर्ण है।

दो चीजें जो वास्तव में प्रदर्शन को मार सकती हैं, मेमोरी ट्रैवर्सल और कचरा संग्रह हैं। यहां तक ​​कि यदि आप बहुत सारे कचरे का उत्पादन नहीं कर रहे हैं, तो मेमोरी ट्रैवर्सल ने सीपीयू कैश पर अधिक दबाव डाला है और अंत में आपकी मेमोरी बस बोतल गर्दन बन जाती है। आपके isStopWord फ़ंक्शन स्ट्रिंग तुलना के बहुत सारे निष्पादित करता है और ऐसा करने के लिए एक लंबी लंबी लिंक्ड सूची को पार करना पड़ता है। आप बहुत काम builtin Set प्रकार का उपयोग और भी बेहतर, HashSet प्रकार unordered-containers पैकेज से (दोहराया स्ट्रिंग के बाद से तुलना महंगा हो सकता है, खासकर अगर वे कॉमन्स उपसर्गों का हिस्सा) को बचा सकता है या,।

import   Data.HashSet    (HashSet) 
import qualified Data.HashSet    as S 

... 

finnishStop :: [Text] 
finnishStop = ["minä", "sinä", "hän", "kuitenkin", "jälkeen", "mukaanlukien", "koska", "mutta", "jos", "kuitenkin", "kun", "kunnes", "sanoo", "sanoi", "sanoa", "miksi", "vielä", "sinun"] 
englishStop :: [Text] 
englishStop = ["a","able","about","across","after","all","almost","also","am","among","an","and","any","are","as","at","be","because","been","but","by","can","cannot","could","dear","did","do","does","either","else","ever","every","for","from","get","got","had","has","have","he","her","hers","him","his","how","however","i","if","in","into","is","it","its","just","least","let","like","likely","may","me","might","most","must","my","neither","no","nor","not","of","off","often","on","only","or","other","our","own","rather","said","say","says","she","should","since","so","some","than","that","the","their","them","then","there","these","they","this","tis","to","too","twas","us","wants","was","we","were","what","when","where","which","while","who","whom","why","will","with","would","yet","you","your"] 

stopWord :: HashSet Text 
stopWord = S.fromList (finnishStop ++ englishStop) 

isStopWord :: Text -> Bool 
isStopWord x = x `S.member` stopWord 

इस संस्करण के साथ अपने isStopWord समारोह की जगह काफी बेहतर करता है और ज्यादा बेहतर मापता है (हालांकि निश्चित रूप से नहीं 1-1)। के कारण Map के बजाय HashMap (उसी पैकेज से) का उपयोग करके पर भी विचार कर सकते हैं, लेकिन मुझे ऐसा करने में कोई उल्लेखनीय परिवर्तन नहीं मिला।

एक और विकल्प डिफ़ॉल्ट ढेर आकार को जीसी से दबाव लेने और चीजों को स्थानांतरित करने के लिए और अधिक जगह देने के लिए है। संकलित कोड को 1 जीबी (-H1G ध्वज) का एक डिफ़ॉल्ट ढेर आकार दिया गया है, मुझे का जीसी संतुलन 4 कोर पर लगभग 50% मिलता है, जबकि मुझे केवल ~ 25% बिना मिलता है (यह ~ 30% तेज़ भी चलाता है)।

इन दो परिवर्तनों के साथ, चार कोर (मेरी मशीन पर) पर औसत रनटाइम ~ 10.5 से ~ 3.5 तक गिरता है। तर्कसंगत रूप से, जीसी आंकड़ों के के आधार पर सुधार के लिए एक कमरा है (अभी भी उत्पादक काम करने में 58% खर्च करता है), लेकिन काफी बेहतर प्रदर्शन करने के लिए आपके एल्गोरिदम में अधिक कठोर परिवर्तन की आवश्यकता हो सकती है।

+3

मैं कठोर परिवर्तनों के लिए खुला हूं। यह सब मेरे बाद सीखना है :) – Masse

4

मुझे लगता है कि डेनियल यह अधिकार मिल गया के लिए जोड़ा गया आयात - Data.Map और सूचियों एक आलसी डेटा संरचनाओं कर रहे हैं; आपको प्रत्येक खंड के लिए काम सुनिश्चित करने के लिए फ़ोल्डल 'और डालने के साथ दोनों का उपयोग करना चाहिए --- अन्यथा सभी कार्य अनुक्रमिक भाग (कम) में देरी हो रही हैं।

यह भी स्पष्ट नहीं है कि प्रत्येक फ़ाइल के लिए स्पार्क बनाना सही ग्रैन्युलरिटी है, खासकर यदि फ़ाइल आकार काफी भिन्न हैं। यदि यह मामला हो सकता है, तो शब्द सूचियों को संयोजित करना और आकार के हिस्सों में विभाजित करना बेहतर होगा (parlistChunk संयोजक देखें)।

जब आप इसमें हों, तो मैं कई फ़ाइलों को खोलने के लिए आलसी आईओ (रीडफाइल) का उपयोग करने के कुछ नुकसान भी देखूंगा (रनटाइम सिस्टेम फाइल हैंडल से बाहर हो सकता है क्योंकि यह बहुत लंबे समय तक उनके पास रहता है)।

+0

जैसा कि मेरी टिप्पणी से देखा गया है, मैंने पैरामैप, parListN और parListChunk की कोशिश की है। सभी में समान प्रदर्शन विशेषताएं हैं। फोल्ड करने के लिए फ़ोल्डर को बदलना 'संतुलन को बढ़ाकर> 2 तक बढ़ा देता है, लेकिन कुल रनटाइम लगभग दोगुना हो गया है। – Masse

+0

मैं कोड में बदल गया ताकि फ़ोल्डर -> फ़ोल्डल 'और मैड्रिड को शब्द सूची से हिस्टोग्राम में ले जाया गया हो। मैंने फाइल को लाइनों में विभाजित किया और मैप्रिडस के भीतर मैं parListChunk stratm (100) xs का उपयोग करता हूं। मैंने रनटाइम को सफलतापूर्वक चौगुनी (~ 70 सेकंड से 300 सेकंड तक) – Masse