2011-01-04 11 views
6

के साथ समानांतर रणनीतियों का उपयोग करके मैं अक्सर शुद्ध कंप्यूटेशंस से जुड़े हास्केल की समानांतर रणनीतियों के उपयोग और स्पष्टीकरण को देखता हूं (उदाहरण के लिए fib)। हालांकि, मुझे अक्सर इसे मोनैडिक निर्माण के साथ उपयोग नहीं किया जाता है: क्या par और ST s या IO पर लागू होने पर संबंधित कार्यों की उचित व्याख्या है? क्या इस तरह के उपयोग से कोई गति प्राप्त की जाएगी? आईओ इकाई मेंमोनैड

+0

आप अपने आईओ क्रियाओं को एक निश्चित क्रम में निष्पादित करना चाहते हैं (उदाहरण के लिए इसे बंद करने से पहले फ़ाइल को खोलें, इसे पढ़ने से पहले)। आप वहां समानांतर करना चाहते हैं? – helium

+1

@helium: यह ज्यादातर म्यूटेबल डेटा या एफएफआई का उपयोग करते समय आता है। –

+0

मैंने यह सोचा है। मैं अक्सर कई बड़ी फाइलें (100 मेग्स) खोलता हूं और उन्हें समानांतर धागे में अनजिप करता हूं और फिर खुले होने के बाद उनके साथ काम करता हूं। वे एक अच्छा प्रदर्शन सुधार देखने के लिए काफी बड़े हैं लेकिन काफी छोटे हैं, मैं उन्हें स्मृति में रख सकता हूं। मैंने सोचा है कि हास्केल में ऐसा कैसे करें। –

उत्तर

12

समानता अधिक सही ढंग से "कन्करेंसी" कहा जाता है, और Control.Concurrent मॉड्यूल में forkIO और दोस्तों के द्वारा समर्थित है।

एसटी मोनैड के समानांतरता में कठिनाई यह है कि एसटी आवश्यक रूप से सिंगल-थ्रेडेड है - यह इसका उद्देश्य है। एसटी मोनड, Control.Monad.ST.Lazy का आलसी संस्करण है, जो सैद्धांतिक रूप से समांतर मूल्यांकन का समर्थन कर सकता है, लेकिन मुझे ऐसा करने की कोशिश करने वाले किसी के बारे में पता नहीं है।

Eval नामक समानांतर मूल्यांकन के लिए एक नया मोनड है, जो parallel package के हाल के संस्करणों में पाया जा सकता है। मैं इन दिनों Eval मोनैड rpar और par और pseq के बजाय इन दिनों की तुलना करने की सलाह देता हूं, क्योंकि इससे अधिक मजबूत और पठनीय कोड होता है। उदाहरण के लिए, हमेशा की तरह fib उदाहरण

fib n = if n < 2 then 1 else 
     runEval $ do 
      x <- rpar (fib (n-1)) 
      y <- rseq (fib (n-2)) 
      return (x+y) 
1

लिखा जा सकता है, जहां इस समझ में आता है कुछ स्थितियों रहे हैं, लेकिन सामान्य रूप में आप यह कर नहीं होना चाहिए। की जांच के बाद:

doPar = 
    let a = unsafePerformIO $ someIOCalc 1 
     b = unsafePerformIO $ someIOCalc 2 
    in a `par` b `pseq` a+b 
doPar में

, a के लिए एक गणना छिड़ जाता है, तो मुख्य थ्रेड का मूल्यांकन करता है b। लेकिन, यह संभव है कि मुख्य धागे के बाद b की गणना समाप्त हो जाए, तो यह a का भी मूल्यांकन करना शुरू कर देगा। अब आपके पास a का मूल्यांकन करने वाले दो धागे हैं, जिसका अर्थ है कि कुछ आईओ क्रियाएं दो बार (या संभवतः अधिक) की जाएगी। लेकिन अगर एक धागा a का मूल्यांकन खत्म कर देता है, तो दूसरा अभी तक जो कुछ भी किया गया है उसे छोड़ देगा। इसे सुरक्षित रखने के लिए, आपको कुछ चीजों को सत्य होने की आवश्यकता है:

  1. आईओ क्रियाओं को कई बार किया जाना सुरक्षित है।
  2. यह केवल कुछ आईओ क्रियाओं के लिए सुरक्षित है (उदाहरण के लिए कोई सफाई नहीं है)
  3. आईओ क्रिया किसी भी दौड़ की स्थिति से मुक्त हैं। यदि a का मूल्यांकन करते समय एक थ्रेड कुछ डेटा को बदल देता है, तो क्या अन्य थ्रेड a पर भी काम करेगा? शायद ऩही।
  4. किसी भी विदेशी कॉल कर रहे हैं फिर से प्रवेशी

यह par और के साथ इस का उपयोग करने के लिए पूरी तरह सुरक्षित नहीं है अपने someIOCalc इस

someIOCalc n = do 
    prelaunchMissiles 
    threadDelay n 
    launchMissiles 

जैसा दिखाई देता है (आप निश्चित रूप से सामान्य रूप में संगामिति के लिए इस की जरूरत है) unsafePerformIO

अब, क्या यह कभी इसके लायक है? शायद। स्पार्क्स सस्ते हैं, धागे से भी सस्ता हैं, इसलिए सिद्धांत में यह एक प्रदर्शन लाभ होना चाहिए। अभ्यास में, शायद इतना नहीं। रोमन Leschinsky एक अच्छा blog post about this है।

व्यक्तिगत रूप से, मुझे forkIO के कारण के कारण यह बहुत आसान लगता है।

संबंधित मुद्दे