2013-01-02 23 views
41

में साझा स्मृति में मेरे पास तीन बड़ी सूचियां हैं। पहले बिटरैरे (मॉड्यूल बिटरैर 0.8.0) और अन्य दो में पूर्णांक के सरणी होते हैं।मल्टीप्रोसेसिंग

l1=[bitarray 1, bitarray 2, ... ,bitarray n] 
l2=[array 1, array 2, ... , array n] 
l3=[array 1, array 2, ... , array n] 

ये डेटा संरचनाएं काफी RAM (~ 16GB कुल) लेती हैं।

तो मैं का उपयोग कर 12 उप प्रक्रियाओं शुरू:

multiprocessing.Process(target=someFunction, args=(l1,l2,l3)) 

इसका मतलब यह है कि एल 1, एल 2 और L3 प्रत्येक उप-प्रक्रिया के लिए कॉपी किया जायेगा या उप प्रक्रियाओं इन सूचियों का हिस्सा होगा? या अधिक प्रत्यक्ष होने के लिए, क्या मैं 16 जीबी या 1 9 2 जीबी रैम का उपयोग करूंगा?

कुछ फ़ंक्शन इन सूचियों से कुछ मान पढ़ेगा और फिर पढ़ने वाले मानों के आधार पर कुछ गणनाएं करेगा। परिणाम माता-पिता को वापस कर दिए जाएंगे। सूची L1, l2 और l3 को कुछ फ़ंक्शन द्वारा संशोधित नहीं किया जाएगा।

इसलिए मुझे लगता है कि उप-प्रक्रियाओं की आवश्यकता नहीं है और इन विशाल सूचियों की प्रतिलिपि नहीं होगी बल्कि बदले में उन्हें माता-पिता के साथ साझा करेंगे। इसका मतलब है कि लिनक्स के तहत कॉपी-ऑन-राइट दृष्टिकोण के कारण कार्यक्रम में 16 जीबी रैम लगेगा (चाहे कितनी उप-प्रक्रियाएं शुरू हों)? क्या मैं सही हूं या क्या मुझे ऐसा कुछ याद आ रहा है जिससे सूचियों की प्रतिलिपि बनाई जा सके?

EDIT: मैं अभी भी इस विषय पर थोड़ा और पढ़ने के बाद उलझन में हूं। एक तरफ लिनक्स कॉपी-ऑन-राइट का उपयोग करता है, जिसका मतलब यह होना चाहिए कि कोई डेटा कॉपी नहीं किया गया है। दूसरी तरफ, ऑब्जेक्ट तक पहुंचने से इसकी रेफ-गिनती बदल जाएगी (मुझे अभी भी अनिश्चितता है कि इसका मतलब क्यों है और इसका क्या अर्थ है)। फिर भी, क्या पूरी वस्तु की प्रतिलिपि बनाई जाएगी?

उदाहरण के लिए

इस प्रकार अगर मैं someFunction को परिभाषित:

def someFunction(list1, list2, list3): 
    i=random.randint(0,99999) 
    print list1[i], list2[i], list3[i] 

का उपयोग कर सकते हैं इस समारोह का मतलब है कि एल 1, एल 2 और L3 प्रत्येक उप-प्रक्रिया के लिए पूरी तरह से कॉपी किया जायेगा?

क्या यह जांचने का कोई तरीका है?

EDIT2 कुछ और पढ़ने के बाद और सिस्टम की कुल मेमोरी उपयोग की निगरानी करते समय उप-प्रक्रियाएं चल रही हैं, ऐसा लगता है कि पूरी ऑब्जेक्ट्स वास्तव में प्रत्येक उप-प्रक्रिया के लिए प्रतिलिपि बनाई जाती हैं। और ऐसा लगता है क्योंकि संदर्भ गिनती है।

एल 1, एल 2 और एल 3 के लिए संदर्भ गणना वास्तव में मेरे कार्यक्रम में अनियंत्रित है। ऐसा इसलिए है क्योंकि एल 1, एल 2 और एल 3 को स्मृति (अपरिवर्तित) में रखा जाएगा जब तक माता-पिता प्रक्रिया समाप्त न हो जाए। तब तक इन सूचियों द्वारा उपयोग की जाने वाली स्मृति को मुक्त करने की आवश्यकता नहीं है। वास्तव में मुझे यह सुनिश्चित करने के लिए पता है कि जब तक प्रोग्राम बाहर निकलता है तो संदर्भ गणना 0 से ऊपर (इन सूचियों और इन सूचियों में प्रत्येक वस्तु के लिए) रहेगी।

तो अब प्रश्न बन जाता है, मैं कैसे सुनिश्चित कर सकता हूं कि वस्तुओं को प्रत्येक उप-प्रक्रिया में कॉपी नहीं किया जाएगा? क्या मैं शायद इन सूचियों और इन सूचियों में प्रत्येक ऑब्जेक्ट के लिए संदर्भ गिनती अक्षम कर सकता हूं?

EDIT3 बस एक अतिरिक्त नोट। उप-प्रक्रियाओं को l1, l2 और l3 या इन सूचियों में से किसी भी ऑब्जेक्ट को संशोधित करने की आवश्यकता नहीं है। उप-प्रक्रियाओं को केवल प्रत्येक उप-प्रक्रिया के लिए स्मृति की प्रतिलिपि बनाने के बिना इन वस्तुओं में से कुछ को संदर्भित करने में सक्षम होना चाहिए।

+0

http://stackoverflow.com/questions/10721915/shared-memory-objects-in-python -multiprocessing इसी तरह का सवाल और आपका जवाब। – sean

+0

रीड इसे धोखा देती है और अभी भी उत्तर के बारे में अनिश्चित है। क्या पूरी वस्तु की प्रतिलिपि बनाई जाएगी? वस्तु का केवल एक हिस्सा? केवल पृष्ठ जिसमें refcount शामिल है? मैं कैसे जांच सकता हूँ? – FableBlaze

+0

कॉपी-ऑन-राइट के कारण, मुझे लगता है कि आपको कुछ भी विशेष नहीं करना चाहिए। क्यों न सिर्फ कोशिश करें? – NPE

उत्तर

31

सामान्य शब्दों में, वहाँ एक ही डाटा साझा करने के लिए दो तरीके हैं:

  • बहु सूत्रण
  • साझा स्मृति

पायथन के बहु सूत्रण जीआईएल की वजह से सीपीयू बाध्य कार्यों के लिए उपयुक्त (नहीं है), इसलिए उस मामले में सामान्य समाधान multiprocessing पर जाना है। हालांकि, इस समाधान के साथ आपको multiprocessing.Value और multiprocessing.Array का उपयोग करके डेटा को स्पष्ट रूप से साझा करने की आवश्यकता है।

ध्यान दें कि आमतौर पर प्रक्रियाओं के बीच डेटा साझा सबसे अच्छा विकल्प, सभी तुल्यकालन मुद्दों की वजह से नहीं हो सकता है; संदेशों का आदान-प्रदान करने वाले अभिनेताओं से जुड़े एक दृष्टिकोण को आमतौर पर बेहतर विकल्प के रूप में देखा जाता है। भी Python documentation देखें:

ऊपर उल्लेख किया है, जब समवर्ती प्रोग्रामिंग कर यह आम तौर पर सबसे अच्छा है जहाँ तक संभव हो साझा राज्य का उपयोग से बचने के लिए। यह एकाधिक प्रक्रियाओं का उपयोग करते समय विशेष रूप से सच है।

हालांकि, अगर आपको वास्तव में कुछ साझा डेटा का उपयोग करने की आवश्यकता है तो मल्टीप्रोसेसिंग ऐसा करने के कुछ तरीके प्रदान करता है।

आपके मामले में, आप (एक multiprocessing.Array का उपयोग करके जैसे) l1, l2 और l3 किसी तरह multiprocessing द्वारा समझा जा सकता में रैप करने के लिए, और फिर उन्हें पैरामीटर के रूप में पारित की जरूरत है।
भी ध्यान रखें कि, जैसा कि आप ने कहा कि आपके पास लेखन पहुंच की जरूरत नहीं है, तो आप lock=False पास करना चाहिए, जबकि वस्तुओं बनाने, या सभी का उपयोग अभी भी धारावाहिक की जाएगी।

+0

क्या मैं 'bitipray()' जैसी मनमानी वस्तुओं की सूचियों को लपेटने के लिए 'multiprocessing.Array' का उपयोग कर सकता हूं? – FableBlaze

+0

@ anti666: मुझे लगता है कि आपको 'multiprocessing.sharedctypes' का उपयोग करना चाहिए - http://docs.python.org/2/library/multiprocessing.html#module-multiprocessing.sharedctypes –

+1

वैकल्पिक रूप से, यदि बिटरैर प्रोटोकॉल बफर का समर्थन करता है, तो आप इसे एक बाइटियर के रूप में साझा कर सकता है, और उसके बाद इसे वापस प्रक्रियाओं में बिटरैरे में परिवर्तित कर सकता है। –

9

आप कॉपी-ऑन-राइट सुविधा का उपयोग करना चाहते हैं और अपने डेटा स्थिर (बच्चे की प्रक्रिया में कोई बदलाव नहीं) है - आप अजगर स्मृति ब्लॉक जहां अपने डेटा निहित है के साथ गड़बड़ नहीं है बनाना चाहिए। आप आसानी से कंटेनर के रूप में सी या सी ++ ढांचे (उदाहरण के लिए एसटीएल) का उपयोग करके ऐसा और कहा कि (या संभवतः डेटा मेम कॉपी) डेटा स्मृति की ओर इशारा का उपयोग करेगा जब अजगर स्तरीय वस्तु यदि कोई सब पर बनाया जाएगा अपने खुद के अजगर रैपर प्रदान कर सकते हैं । यह सब लगभग अजगर सादगी और cython साथ वाक्य रचना के साथ बहुत आसानी से किया जा सकता है।

 
# pseudo cython 
cdef class FooContainer: 
    cdef char * data 
    def __cinit__(self, char * foo_value): 
     self.data = malloc(1024, sizeof(char)) 
     memcpy(self.data, foo_value, min(1024, len(foo_value))) 

    def get(self): 
     return self.data 

 
# python part 
from foo import FooContainer 

f = FooContainer("hello world") 
pid = fork() 
if not pid: 
    f.get() # this call will read same memory page to where 
      # parent process wrote 1024 chars of self.data 
      # and cython will automatically create a new python string 
      # object from it and return to caller 

ऊपर छद्म कोड बुरी तरह से लिखा जाता है। इसका इस्तेमाल न करें। Self.data के स्थान पर आपके मामले में सी या सी ++ कंटेनर होना चाहिए।

0

आप एक महत्वपूर्ण मूल्य जोड़ी के रूप में memcached या redis का उपयोग करें और सेट कर सकते हैं प्रत्येक { 'एल 1' ...

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