2012-04-04 17 views
13

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

यह समानांतर एन क्वींस के लिए कोड,

import Control.Monad 
import System.Environment 
import GHC.Conc 
import Control.Parallel.Strategies 
import Data.List 
import Data.Function 

type PartialSolution = [Int] -- per column, list the row the queen is in 
type Solution = PartialSolution 

type BoardSize = Int 

chunk :: Int -> [a] -> [[a]] 
chunk n [] = [] 
chunk n xs = case splitAt n xs of 
     (ys, zs) -> ys : chunk n zs 

-- Generate all solutions for a given board size. 
queens :: BoardSize -> [Solution] 
--queens n = iterate (concatMap (addQueen n)) [[]] !! n 
queens n = iterate (\l -> concat (map (addQueen n) l `using` parListChunk (n `div`   numCapabilities) rdeepseq)) [[]] !! n 


-- Given the size of the problem and a partial solution for the 
-- first few columns, find all possible assignments for the next 
-- column and extend the partial solution. 
addQueen :: BoardSize -> PartialSolution -> [PartialSolution] 
addQueen n s = [ x : s | x <- [1..n], safe x s 1 ] 

-- Given a row number, a partial solution and an offset, check 
-- that a queen placed at that row threatens no queen in the 
-- partial solution. 
safe :: Int -> PartialSolution -> Int -> Bool 
safe x [] n = True 
safe x (c:y) n = x /= c && x /= c + n && x /= c - n && safe x y (n + 1) 

main = do 
     [n] <- getArgs 
     print $ length $ queens (read n) 

लाइन (\l -> concat (map (addQueen n) l using parListChunk (n div numCapabilities) rdeepseq)) मैं क्या मूल कोड से बदल रहा है। मैंने साइमन मार्लो के समाधान को देखा है लेकिन मैं अपने कोड में मंदी और त्रुटि के कारण को जानना चाहता था।

अग्रिम धन्यवाद।

+1

आप कैसे संकलित किया था और चला सकता हूँ? – is7s

+3

क्या आप '-O2' के साथ संकलित हैं और' -थ्रेडेड-एनएन 'के साथ चल रहे हैं (जहां आपकी सीपीयू गिनती है?) –

+0

ध्यान दें कि' -थ्रेडेड 'एक संकलित समय विकल्प है, रन टाइम विकल्प नहीं है। इसके अलावा, आप बेली के वापस कब आ रहे हैं, डॉन? नल आपको याद करते हैं। –

उत्तर

4

आप बहुत अधिक काम कर रहे हैं। parListChunkdiv n numCapabilities का पैरामीटर शायद आपके सिस्टम पर 7, 2 कोर और आप एन ~ 14 के साथ चल रहे हैं)। सूची बहुत तेजी से बढ़ने जा रही है, इसलिए काम की ऐसी छोटी इकाइयों को चमकाने में कोई बात नहीं है (और मुझे नहीं लगता कि यह n के मूल्य पर क्यों लगा रहा है)।

यदि मैं दस का कारक जोड़ता हूं (इस मामले में स्पार्किंग इकाई 70 बना रहा हूं) तो मुझे सिंगल थ्रेडिंग पर स्पष्ट प्रदर्शन जीत मिलती है। साथ ही, मेरे पास स्टैक समस्या नहीं है जिसका आप उल्लेख करते हैं - यदि यह आपके parListChunk मान में परिवर्तन के साथ चला जाता है तो मैं उस बग के रूप में रिपोर्ट करूंगा।

यदि मैं हर 800 को तोड़ देता हूं तो समय 5.375 के बनाम 7.9 के ऊपर रहता है। 800 से अधिक और प्रदर्शन फिर से खराब हो जाना शुरू होता है, ymmv।

संपादित करें:

[[email protected] Test]$ ghc --version 
The Glorious Glasgow Haskell Compilation System, version 7.0.4 
[[email protected] Test]$ ghc -O2 so.hs -rtsopts -threaded -fforce-recomp ; time ./so 13 +RTS -N2 
[1 of 1] Compiling Main    (so.hs, so.o) 
Linking so ... 
73712 
real 0m5.404s 

[[email protected] Test]$ ghc -O2 so.hs -rtsopts -fforce-recomp ; time ./so 13 
[1 of 1] Compiling Main    (so.hs, so.o) 
Linking so ... 
73712 
real 0m8.134s 
+0

उस गलती को इंगित करने के लिए धन्यवाद। मैं वास्तव में कोर के बीच समान आंशिक समाधान विभाजित करना चाहता था। अब मैंने इसे 'div (length l) numCapabilities' के रूप में संशोधित किया है जो ठीक होना चाहिए। ऐसा करने के बाद भी मुझे लगता है कि समांतर संस्करण अनुक्रमिक संस्करण (संकलित विकल्प के बिना संकलित) से धीमा है और -एन 1 विकल्प के लिए मुझे एक ही स्टैक ओवरफ़्लो अपवाद मिलता है। जब मैं बोर्ड आकार 14 के लिए कोशिश करता हूं, अनुक्रमिक संस्करण ठीक काम करता है लेकिन समांतर संस्करण स्मृति त्रुटि से बाहर देता है। – prasannak

+0

मुझे पता है कि यह जानकारी पर्याप्त नहीं हो सकती है, अगर मैं इन मामलों के लिए इवेंट लॉग फ़ाइल संलग्न कर सकता हूं तो इससे मदद मिलेगी? – prasannak

+0

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