2013-02-07 15 views
8

मैं एक कार्यक्रम निम्नानुसार संक्षेप किया जा सकता है कि लिखा है:अजगर बहु ​​स्मृति उपयोग

def loadHugeData(): 
    #load it 
    return data 

def processHugeData(data, res_queue): 
    for item in data: 
     #process it 
     res_queue.put(result) 
    res_queue.put("END") 

def writeOutput(outFile, res_queue): 
    with open(outFile, 'w') as f 
     res=res_queue.get() 
     while res!='END': 
      f.write(res) 
      res=res_queue.get() 

res_queue = multiprocessing.Queue() 

if __name__ == '__main__': 
    data=loadHugeData() 
    p = multiprocessing.Process(target=writeOutput, args=(outFile, res_queue)) 
    p.start() 
    processHugeData(data, res_queue) 
    p.join() 

असली (विशेष रूप से'writeOutput() ') कोड एक बहुत अधिक जटिल है। 'writeOutput() 'केवल इन मानों का उपयोग करता है जो इसका तर्क (अर्थात् यह संदर्भ नहीं करता है'

असल में यह स्मृति में एक विशाल डेटासेट लोड करता है और इसे संसाधित करता है। आउटपुट का लेखन उप-प्रक्रिया में दिया जाता है (यह वास्तव में कई फाइलों में लिखता है और इसमें बहुत समय लगता है)। इसलिए प्रत्येक बार जब एक डेटा आइटम संसाधित हो जाता है तो इसे उप-प्रोसेस ट्रॉफ res_queue पर भेजा जाता है जो बदले में परिणामस्वरूप फ़ाइलों को परिणाम में लिखता है।

उप-प्रक्रिया को किसी भी तरह से'loadHugeData() 'द्वारा लोड किए गए डेटा को एक्सेस, पढ़ने या संशोधित करने की आवश्यकता नहीं है। उप-प्रक्रिया को केवल उस प्रक्रिया का उपयोग करने की आवश्यकता होती है जो मुख्य प्रक्रिया इसे 'gres_queue' को भेजती है। और यह मुझे मेरी समस्या और सवाल की ओर ले जाता है।

ऐसा लगता है कि उप-प्रक्रिया विशाल डेटासेट की प्रतिलिपि पर होती है (जब'top' 'के साथ मेमोरी उपयोग की जांच होती है)। क्या ये सच है? और यदि ऐसा है तो मैं आईडी से कैसे बच सकता हूं (डबल मेमोरी का उपयोग करके)?

मैं पायथन 2.6 का उपयोग कर रहा हूं और प्रोग्राम लिनक्स पर चल रहा है।

+0

क्या आप अपने कोड को पुन: लोड करने के बजाय पुनर्विक्रेता का उपयोग करने के लिए पुन: स्थापित कर सकते हैं? ऐसा प्रतीत होता है कि अगर ऐसा लगता है कि लोड/प्रक्रिया/एनक्यू/डेक्यू/लिखना – sotapme

+0

दुर्भाग्य से एक टैब-पृथक txt फ़ाइल मूल रूप से एक स्पैस सरणी है। और मुझे प्रोसेसिंग के दौरान लाइन नंबर के आधार पर इस डेटा में "यादृच्छिक पहुंच" की आवश्यकता है। इसलिए इसे स्मृति में लोड करना (स्पैस सरणी विशिष्ट अनुकूलन के साथ) बहुत तेजी से प्रसंस्करण करता है। – FableBlaze

+0

यह प्रक्रिया एकीकरण करने के लिए '[beanstalkd] (https://github.com/earl/beanstalkc/blob/master/TUTORIAL.mkd) जैसे कुछ का उपयोग करने का सुझाव देने के लिए बड़े पैमाने पर ओवर-इंजीनियरिंग हो सकता है लेकिन यह जानना दिलचस्प होगा अगर यह मदद/स्केल/perfomed मदद की। हमेशा की तरह अन्य लोगों की समस्याएं हमेशा अधिक दिलचस्प होती हैं। – sotapme

उत्तर

13

multiprocessing मॉड्यूल प्रभावी रूप से fork सिस्टम कॉल पर आधारित है जो वर्तमान प्रक्रिया की एक प्रति बनाता है। चूंकि आप fork (या multiprocessing.Process) से पहले विशाल डेटा लोड कर रहे हैं, इसलिए बच्चे की प्रक्रिया डेटा की एक प्रति प्राप्त करती है।

हालांकि, अगर ऑपरेटिंग सिस्टम आप गाय (प्रतिलिपि लिखने) पर चल रहे हैं, तो वास्तव में भौतिक स्मृति में डेटा की एक प्रति होगी जब तक आप माता-पिता या बाल प्रक्रिया में डेटा को संशोधित नहीं करते हैं (माता-पिता और बच्चे दोनों साझा करेंगे समान भौतिक स्मृति पृष्ठ, हालांकि विभिन्न वर्चुअल एड्रेस रिक्त स्थान में); और फिर भी, अतिरिक्त मेमोरी केवल परिवर्तनों के लिए आवंटित की जाएगी (pagesize वृद्धि में)।

आप अपने विशाल डेटा को लोड करने से पहले multiprocessing.Process पर कॉल करके इस स्थिति से बच सकते हैं। तब जब आप माता-पिता में डेटा लोड करते हैं तो अतिरिक्त स्मृति आवंटन बाल प्रक्रिया में दिखाई नहीं देगा।

+1

मेरे से तेज़ तेज़ी से किया गया। लिनक्स गाय है इसलिए जिस समय पैरेंट प्रक्रिया डेटा को लिखती है, डेटा डुप्लिकेट किया जाएगा। यदि अभिभावक प्रक्रिया केवल डेटा को पढ़ती है तो डेटा का केवल एक उदाहरण होगा ** लेकिन ** शीर्ष (मुझे लगभग यकीन है) डेटा दोनों प्रक्रियाओं से संबंधित डेटा दिखाएगा। meminfo स्मृति उपयोग पर अधिक सटीक संख्या प्रदान करना चाहिए। वास्तव में –

+0

। मुझे लगता है कि इन दिनों सबसे आम ओएस गाय हैं (मैं बस जितना संभव हो उतना सामान्य होने की कोशिश कर रहा था)। ग्रेट फीचर लेकिन प्रक्रिया-आधारित मेमोरी रिपोर्टिंग टूल्स (यानी शीर्ष, पीएस, इत्यादि ...) के आउटपुट की व्याख्या करते समय अक्सर भ्रम पैदा करता है।लिनक्स पर 'meminfo' ठीक से रिपोर्ट करेगा जैसा सोलारिस पर' pmap' होगा; हालांकि विंडोज के बारे में कोई जानकारी नहीं :) – isedev

+5

ध्यान दें कि प्रत्येक पायथन ऑब्जेक्ट में एक संदर्भ गणना होती है जिसे ऑब्जेक्ट तक पहुंचने पर संशोधित किया जाता है। इसलिए, केवल डेटा संरचना को पढ़ने से गाय कॉपी हो सकती है। –

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