मैं एक किरण-अनुरेखक को समानांतर बनाने की कोशिश कर रहा हूं। इसका मतलब है कि मेरे पास छोटी संगणना की बहुत लंबी सूची है। वेनिला कार्यक्रम 67.98 सेकंड में विशिष्ट दृश्य और 13 एमबी कुल मेमोरी उपयोग और 99.2% उत्पादकता पर चलता है।
अपने पहले प्रयास में मैंने parBuffer
50 के बफर आकार के साथ समानांतर रणनीति का उपयोग किया । मैंने चुना parBuffer
क्योंकि यह सूची के माध्यम से चलता है जितनी तेजी से स्पार्क्स का सेवन किया जाता है, और इस तरह की सूची की रीढ़ को मजबूर नहीं करता है parList
, जो बहुत अधिक मेमोरी का उपयोग करेगा चूंकि सूची बहुत लंबी है। इसके साथ -N2
, यह 100.46 सेकंड और 14 एमबी कुल मेमोरी उपयोग और 97.8% उत्पादकता के समय में चला गया। स्पार्क जानकारी है:SPARKS: 480000 (476469 converted, 0 overflowed, 0 dud, 161 GC'd, 3370 fizzled)
फ़िज़ल्ड स्पार्क्स का बड़ा अनुपात इंगित करता है कि स्पार्क्स की ग्रैन्युलैरिटी बहुत छोटी थी, इसलिए अगली बार मैंने रणनीति का उपयोग करने की कोशिश की parListChunk
, जो सूची को विखंडू में विभाजित करती है और प्रत्येक चंक के लिए एक स्पार्क बनाती है। मुझे चंक साइज़ के साथ सबसे अच्छे परिणाम मिले 0.25 * imageWidth
। कार्यक्रम 93.43 सेकंड में चला गया और कुल मेमोरी उपयोग की 236 एमबी और 97.3% उत्पादकता है। चिंगारी जानकारी है: SPARKS: 2400 (2400 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
। मेरा मानना है कि बहुत अधिक मेमोरी का उपयोग होता है क्योंकि parListChunk
सूची की रीढ़ को मजबूर करता है।
फिर मैंने अपनी रणनीति लिखने की कोशिश की कि आलस ने सूची को विखंडू में विभाजित कर दिया और फिर विखंडू को पारित कर दिया parBuffer
और परिणामों को संक्षिप्त कर दिया।
concat $ withStrategy (parBuffer 40 rdeepseq) (chunksOf 100 (map colorPixel pixels))
यह 95.99 सेकंड और 22MB कुल मेमोरी उपयोग और 98.8% उत्पादकता में चला। यह इस अर्थ में सफल था कि सभी स्पार्क्स को परिवर्तित किया जा रहा है और मेमोरी का उपयोग बहुत कम है, हालांकि गति में सुधार नहीं हुआ है। यहाँ Eventlog प्रोफ़ाइल के भाग की एक छवि है।
जैसा कि आप देख सकते हैं कि ढेर के ढेर के कारण धागे बंद हो रहे हैं। मैंने जोड़ने की कोशिश की +RTS -M1G
जो डिफ़ॉल्ट ढेर के आकार को 1Gb तक बढ़ाता है। नतीजे नहीं बदले। मैंने पढ़ा कि हास्केल मुख्य धागा ढेर से मेमोरी का उपयोग करेगा यदि उसका स्टैक ओवरफ्लो होता है, तो मैंने डिफ़ॉल्ट स्टैक का आकार बढ़ाने की भी कोशिश की +RTS -M1G -K1G
लेकिन इसका भी कोई प्रभाव नहीं पड़ा।
क्या यहां कुछ और है जिसके लिए मैं कोशिश कर सकता हूं? मैं मेमोरी उपयोग या ईवेंटलॉग के लिए अधिक विस्तृत रूपरेखा जानकारी पोस्ट कर सकता हूं यदि आवश्यक हो, तो मैंने यह सब शामिल नहीं किया क्योंकि यह बहुत सारी जानकारी है और मुझे नहीं लगता कि इसमें सभी को शामिल करना आवश्यक था।
संपादित करें: मैं हास्केल आरटीएस मल्टीकोर समर्थन के बारे में पढ़ रहा था , और यह प्रत्येक कोर के लिए एक एचईसी (हास्केल एक्ज़ेक्यूशन संदर्भ) होने के बारे में बात करता है। प्रत्येक एचईसी में अन्य बातों के अलावा, एक आवंटन क्षेत्र (जो एक एकल साझा ढेर का एक हिस्सा है) शामिल है। जब भी किसी एचईसी के आवंटन क्षेत्र को समाप्त किया जाता है, तो कचरा संग्रह किया जाना चाहिए। यह नियंत्रित करने के लिए एक आरटीएस विकल्प प्रतीत होता है , -ए। मैंने -A32M की कोशिश की, लेकिन कोई अंतर नहीं देखा।
EDIT2: यहाँ इस सवाल के लिए समर्पित एक गितुब रेपो की एक कड़ी है । मैंने रूपरेखा फ़ोल्डर में प्रोफाइलिंग परिणामों को शामिल किया है।
EDIT3: यहां प्रासंगिक बिट कोड है:
render :: [([(Float,Float)],[(Float,Float)])] -> World -> [Color]
render grids world = cs where
ps = [ (i,j) | j <- reverse [0..wImgHt world - 1] , i <- [0..wImgWd world - 1] ]
cs = map (colorPixel world) (zip ps grids)
--cs = withStrategy (parListChunk (round (wImgWd world)) rdeepseq) (map (colorPixel world) (zip ps grids))
--cs = withStrategy (parBuffer 16 rdeepseq) (map (colorPixel world) (zip ps grids))
--cs = concat $ withStrategy (parBuffer 40 rdeepseq) (chunksOf 100 (map (colorPixel world) (zip ps grids)))
ग्रिड यादृच्छिक फ़्लोट्स होते हैं जो कि पूर्वनिर्मित और कलरपिक्सल द्वारा उपयोग किए जाते हैं। इस प्रकार colorPixel
है:
colorPixel :: World -> ((Float,Float),([(Float,Float)],[(Float,Float)])) -> Color
Strategy
। एक बेहतर शब्द चुनना चाहिए था। इसके अलावा, ढेर अतिप्रवाह मुद्दा भी parListChunk
और साथ होता parBuffer
है।
concat $ withStrategy …
? मैं इस व्यवहार को पुन: पेश नहीं कर सकता6008010
, जो आपके संपादन के लिए निकटतम प्रतिबद्धता है।