मेरे पास कोड का एक टुकड़ा है जो sequence
का उपयोग करके संभाव्यता वितरण से बार-बार नमूने करता है। नैतिक रूप से, यह ऐसा कुछ करता है:एक हास्केल प्रोग्राम प्रोफाइलिंग
sampleMean :: MonadRandom m => Int -> m Float -> m Float
sampleMean n dist = do
xs <- sequence (replicate n dist)
return (sum xs)
सिवाय इसके कि यह थोड़ा और जटिल है। वास्तविक कोड जिसमें मुझे रूचि है likelihoodWeighting
this Github repo पर फ़ंक्शन है।
मैंने देखा कि चलने का समय n
के साथ nonlinearly स्केल करता है। विशेष रूप से, एक बार n
एक निश्चित मान से अधिक हो जाता है, यह स्मृति सीमा को हिट करता है, और चलने का समय विस्फोट होता है। मुझे यकीन नहीं है, लेकिन मुझे लगता है कि ऐसा इसलिए है क्योंकि sequence
उन हिस्सों की एक लंबी सूची तैयार कर रहा है जिन्हें sum
पर कॉल तक मूल्यांकन नहीं किया जा रहा है।
एक बार जब मैं लगभग 100,000 नमूने प्राप्त करता हूं, तो प्रोग्राम क्रॉल में धीमा हो जाता है। मैं इसे अनुकूलित करना चाहता हूं (मेरी भावना यह है कि 10 मिलियन नमूने एक समस्या नहीं होनी चाहिए) इसलिए मैंने इसे प्रोफाइल करने का फैसला किया - लेकिन मुझे प्रोफाइलर के आउटपुट को समझने में थोड़ा परेशानी हो रही है।
रूपरेखा
मैं एक फ़ाइल main.hs
100,000 नमूने के साथ अपने समारोह चलाता है कि में एक छोटी निष्पादन योग्य बनाया। यहाँ
$ ghc -O2 -rtsopts main.hs
$ ./main +RTS -s
पहली बात मैं नोटिस करने से उत्पादन है - यह ढेर के लगभग 1.5 GB आबंटित करता है, और कचरा संग्रहण पर अपने समय का 60% खर्च करता है। क्या यह आम तौर पर बहुत आलस्य का संकेत है?
1,377,538,232 bytes allocated in the heap
1,195,050,032 bytes copied during GC
169,411,368 bytes maximum residency (12 sample(s))
7,360,232 bytes maximum slop
423 MB total memory in use (0 MB lost due to fragmentation)
Generation 0: 2574 collections, 0 parallel, 2.40s, 2.43s elapsed
Generation 1: 12 collections, 0 parallel, 1.07s, 1.28s elapsed
INIT time 0.00s ( 0.00s elapsed)
MUT time 1.92s ( 1.94s elapsed)
GC time 3.47s ( 3.70s elapsed)
RP time 0.00s ( 0.00s elapsed)
PROF time 0.23s ( 0.23s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 5.63s ( 5.87s elapsed)
%GC time 61.8% (63.1% elapsed)
Alloc rate 716,368,278 bytes per MUT second
Productivity 34.2% of total user, 32.7% of total elapsed
यहाँ से
$ ./main +RTS -p
परिणाम पहली बार मैं इस भाग रहे हैं, यह पता चला एक समारोह को बार-बार बुलाया जा रहा था, और यह पता चला कि मैं इसे memoize सकता है, जो चीजों को भागा हालांकि, 2 के कारक से यह अंतरिक्ष रिसाव को हल नहीं किया है।
COST CENTRE MODULE no. entries %time %alloc %time %alloc
MAIN MAIN 1 0 0.0 0.0 100.0 100.0
main Main 434 4 0.0 0.0 100.0 100.0
likelihoodWeighting AI.Probability.Bayes 445 1 0.0 0.3 100.0 100.0
distributionLW AI.Probability.Bayes 448 1 0.0 2.6 0.0 2.6
getSampleLW AI.Probability.Bayes 446 100000 20.0 50.4 100.0 97.1
bnProb AI.Probability.Bayes 458 400000 0.0 0.0 0.0 0.0
bnCond AI.Probability.Bayes 457 400000 6.7 0.8 6.7 0.8
bnVals AI.Probability.Bayes 455 400000 20.0 6.3 26.7 7.1
bnParents AI.Probability.Bayes 456 400000 6.7 0.8 6.7 0.8
bnSubRef AI.Probability.Bayes 454 800000 13.3 13.5 13.3 13.5
weightedSample AI.Probability.Bayes 447 100000 26.7 23.9 33.3 25.3
bnProb AI.Probability.Bayes 453 100000 0.0 0.0 0.0 0.0
bnCond AI.Probability.Bayes 452 100000 0.0 0.2 0.0 0.2
bnVals AI.Probability.Bayes 450 100000 0.0 0.3 6.7 0.5
bnParents AI.Probability.Bayes 451 100000 6.7 0.2 6.7 0.2
bnSubRef AI.Probability.Bayes 449 200000 0.0 0.7 0.0 0.7
यहां एक ढेर प्रोफ़ाइल है। मुझे नहीं पता कि यह रनटाइम का दावा क्यों करता है 1.8 सेकेंड - इस दौड़ में लगभग 6 सेकंड लग गए। अर्थात पहचान करने के लिए जहां टोंटी है, और कैसे चीजें तेजी लाने के लिए सुझाव प्रदान -
किसी को भी मुझे प्रोफाइलर के आउटपुट की व्याख्या करने में मदद कर सकते हैं?
'अनुक्रम के बजाय' replicateM n' का उपयोग करने का प्रयास करें।प्रतिलिपि n' – dflemstr
चलने वाले समय में कोई बदलाव नहीं - संभवतः यह आश्चर्यजनक नहीं है, क्योंकि 'प्रतिकृति एम एन' [परिभाषित] है [http://www.haskell.org/ghc/docs/latest/html/libraries/base/src/नियंत्रण-Monad.html#replicateM) 'अनुक्रम। दोहराना दोहराएं। –
'लंबाई xs' हमेशा' n' है, है ना? तो 'n' के साथ' (लंबाई xs) 'को प्रतिस्थापित करें और फिर 'xs' को किसी भी समय स्मृति में पूरी तरह से निवासी रहने की आवश्यकता नहीं है। – dave4420