2012-09-18 26 views
7

मुझे समझ में नहीं आता क्यों Pipes असुरक्षित कहा जाता है जब एकाधिक प्रेषक और रिसीवर होते हैं।पाइथन मल्टीप्रोसेसिंग पाइप असुरक्षित क्यों हैं?

कैसे निम्नलिखित कोड का उपयोग कर Queues ऐसा तो नहीं है कोड में तब्दील किया जा सकता है? Queues बंद होने पर EOFError फेंक न दें, इसलिए मेरी प्रक्रियाएं रोक नहीं सकती हैं। क्या मुझे अंतहीन रूप से 'जहर' संदेश भेजना चाहिए ताकि उन्हें रोकने के लिए कहा जा सके (इस तरह, मुझे यकीन है कि मेरी सभी प्रक्रियाओं में कम से कम एक जहर प्राप्त होता है)?

मैं जब तक मैं नहीं तो तय (यहां यह जब मैं 10 संदेश भेजे हैं है) पाइप p1 खुला रखने के लिए करना चाहते हैं।


from multiprocessing import Pipe, Process 
from random import randint, random 
from time import sleep 

def job(name, p_in, p_out): 
    print(name + ' starting') 
    nb_msg = 0 
    try: 
     while True: 
      x = p_in.recv() 
      print(name + ' receives ' + x) 
      nb_msg = nb_msg + 1 
      p_out.send(x) 
      sleep(random()) 
    except EOFError: 
     pass 
    print(name + ' ending ... ' + str(nb_msg) + ' message(s)') 

if __name__ == '__main__': 
    p1_in, p1_out = Pipe() 
    p2_in, p2_out = Pipe() 

    proc = [] 

    for i in range(3): 
     p = Process(target=job, args=(str(i), p1_out, p2_in)) 
     p.start() 
     proc.append(p) 

    for x in range(10): 
     p1_in.send(chr(97+x)) 
    p1_in.close() 
    for p in proc: 
     p.join() 
    p1_out.close() 
    p2_in.close() 

    try: 
     while True: 
      print(p2_out.recv()) 
    except EOFError: 
     pass 

    p2_out.close() 

उत्तर

13

अनिवार्य रूप से, समस्या यह है कि Pipe एक मंच से परिभाषित पाइप वस्तु चारों ओर एक पतली आवरण है। recv एक पूर्ण पायथन ऑब्जेक्ट प्राप्त होने तक बार-बार बाइट्स का बफर प्राप्त होता है। यदि दो धागे या प्रक्रियाएं उसी पाइप पर recv का उपयोग करती हैं, तो पाठ प्रत्येक आधे को एक मसालेदार वस्तु के साथ छोड़कर डेटा को दूषित कर सकता है। Queue एस अधिक जटिलता के खर्च पर प्रक्रियाओं के बीच उचित सिंक्रनाइज़ेशन करते हैं।

multiprocessing प्रलेखन का कहना है:

नोट एक पाइप में डेटा दूषित हो सकता है कि अगर दो प्रक्रियाओं (या धागे) से पढ़ने के लिए या एक ही समय में पाइप के एक ही अंत करने के लिए लिखने की कोशिश । बेशक एक ही समय में पाइप के विभिन्न सिरों का उपयोग करके प्रक्रियाओं से भ्रष्टाचार का कोई खतरा नहीं है।

आपको अंतहीन रूप से जहरीले गोलियां भेजने की ज़रूरत नहीं है; प्रति कार्यकर्ता एक है जो आपको चाहिए। प्रत्येक कार्यकर्ता बाहर निकलने से पहले एक जहर गोली मारता है, इसलिए कोई खतरा नहीं है कि कोई कर्मचारी किसी भी तरह से संदेश को याद नहीं करेगा।

आपको "कार्यकर्ता प्रक्रिया" मॉडल को पुनः कार्यान्वित करने के बजाय multiprocessing.Pool का उपयोग करने पर भी विचार करना चाहिए - Pool में कई विधियां हैं जो एकाधिक धागे में काम को वितरित करने में बहुत आसान बनाती हैं।

+0

यदि मैं 'recv' और 'पाइप' का उपयोग करते समय' multiprocessing.Lock() 'का उपयोग करता हूं तो क्या होगा? क्या यह सुरक्षित (और कुशल) बन जाएगा? – thuzhf

+0

यदि आप ऐसा करते हैं, तो आप मूल रूप से 'कतार' के साथ समाप्त हो जाएंगे - 'मल्टीप्रोसेसिंग। क्यूयू' एक 'पाइप' है जो ताले की एक जोड़ी से जुड़ी है (प्रत्येक दिशा के लिए एक)। तो, यह सुरक्षित और उचित रूप से कुशल होगा, लेकिन आप सीधे पहिया को फिर से शुरू कर देंगे - क्यों न केवल 'कतार' का उपयोग करें? – nneonneo

7

मुझे समझ नहीं आता क्यों पाइप्स असुरक्षित कहा जाता है जब वहाँ कई प्रेषकों और रिसीवर है।

आप स्रोत ए और बी एक साथ से एक पाइप में जल डालें, पर विचार करें। पाइप के दूसरे छोर पर, यह पता लगाना असंभव होगा कि पानी का कौन सा हिस्सा ए या बी से आया था, है ना? :)

एक पाइप बाइट स्तर पर डेटा स्ट्रीम ट्रांसपोर्ट करता है। इसके ऊपर एक संचार प्रोटोकॉल के बिना, यह नहीं पता कि एक संदेश क्या है और इसलिए संदेश अखंडता सुनिश्चित नहीं कर सकता है। इसलिए, यह एकाधिक प्रेषकों के साथ पाइप का उपयोग करने के लिए केवल 'असुरक्षित' नहीं है। यह एक प्रमुख डिजाइन दोष है और अधिकतर संचार समस्याओं का कारण बन जाएगा।

कतार, हालांकि, उच्च स्तर पर लागू किए गए हैं। वे संदेश (या यहां तक ​​कि अमूर्त वस्तुओं) को संचारित करने के लिए डिज़ाइन किए गए हैं। संदेश/ऑब्जेक्ट स्वयं निहित रखने के लिए पंक्तियां बनाई जाती हैं। कई स्रोत ऑब्जेक्ट्स को कतार में डाल सकते हैं और कई उपभोक्ता इन ऑब्जेक्ट्स को 100% सुनिश्चित कर सकते हैं, जबकि एक इकाई के रूप में कतार में जो भी हो, वह यूनिट के रूप में भी निकलता है।काफी देर के बाद

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

मैं बाइट स्ट्रीम में उस जोड़ना चाहिए, सभी बाइट्स उसी क्रम में के रूप में भेजा प्राप्त किए गए हैं (गारंटी)। एकाधिक प्रेषकों के साथ समस्या यह है कि प्रेषण आदेश (इनपुट का क्रम) पहले से ही अस्पष्ट या यादृच्छिक हो सकता है, यानी कई धाराएं अप्रत्याशित फैशन में मिल सकती हैं।

एक आम कतार कार्यान्वयन गारंटी देता है कि एकल संदेश बरकरार रखा जाता है, भले ही एकाधिक प्रेषक हों। भेजे गए आदेश में संदेशों को भी पुनर्प्राप्त किया जाता है। कई प्रतिस्पर्धी प्रेषकों के साथ और बिना सिंक्रनाइज़ेशन तंत्र के, फिर भी, इनपुट संदेशों के आदेश के बारे में कोई गारंटी नहीं है।