2011-11-06 17 views
6

ठीक है, क्योंकि वर्तमान में कोई जवाब नहीं है, मुझे ऐसा करने में बहुत बुरा नहीं लगता है। जब मैं इस समस्या का कारण करने के लिए अभी भी क्या वास्तव में पर्दे के पीछे क्या हो रहा है में दिलचस्पी रखता हूँ, मेरी सबसे जरूरी सवाल उन अद्यतन 2 में निर्दिष्ट कर रहे हैं उन जा रहा है,सबप्रोसेस पूर्ण हो जाता है लेकिन अभी भी समाप्त नहीं होता है, जिससे डेडलॉक

क्या एक JoinableQueue और एक Manager().Queue() के बीच मतभेद रहे हैं (और आप दूसरे पर एक का उपयोग कब करना चाहिए?)। और महत्वपूर्ण बात यह है कि, इस उदाहरण में, दूसरे के लिए एक को बदलने के लिए सुरक्षित है?


निम्नलिखित कोड में, मेरे पास एक सरल प्रक्रिया पूल है। प्रत्येक प्रक्रिया को प्रोसेस क्यूई (pq) से संसाधित करने के लिए डेटा को खींचने के लिए, और रिटर्न-वैल्यू कतार (rq) को प्रोसेस के लौटाए गए मानों को मुख्य थ्रेड पर वापस करने के लिए पारित किया जाता है। अगर मैं रिटर्न-वैल्यू कतार में शामिल नहीं हूं तो यह काम करता है, लेकिन जैसे ही मैं करता हूं, किसी कारण से प्रक्रियाओं को रोकने से अवरुद्ध कर दिया जाता है। दोनों मामलों में प्रक्रिया run विधियों की वापसी होती है, इसलिए यह वापसी-कतार अवरोधन पर put नहीं है, लेकिन दूसरे मामले में प्रक्रियाएं स्वयं समाप्त नहीं होती हैं, इसलिए प्रक्रियाओं पर join जब प्रोग्राम deadlocks। यह क्यों होगा?

अपडेट:

  1. यह कतार में आइटम्स की संख्या के साथ के लिए कुछ है लगता है।

    कम से कम मेरी मशीन पर, मेरे पास कतार में 6570 आइटम हो सकते हैं और यह वास्तव में काम करता है, लेकिन इससे भी अधिक और यह deadlocks।

  2. यह Manager().Queue() के साथ काम करता प्रतीत होता है।

    चाहे यह JoinableQueue की सीमा है या सिर्फ मुझे दो वस्तुओं के बीच मतभेदों को गलत समझना है, मैंने पाया है कि अगर मैं Manager().Queue() के साथ रिटर्न कतार को प्रतिस्थापित करता हूं, तो यह अपेक्षा के अनुसार काम करता है। उनके बीच मतभेद क्या हैं, और आप दूसरे पर एक का उपयोग कब करना चाहिए?

  3. अगर मैं से rq

    Oop लेने वाली हूँ त्रुटि नहीं होती है। एक पल के लिए यहां एक जवाब था, और जैसा कि मैं इस पर टिप्पणी कर रहा था, यह गायब हो गया। वैसे भी जो कुछ भी कहा गया था, उस पर सवाल उठा रहा था कि क्या, यदि मैं उपभोक्ता जोड़ता हूं तो यह त्रुटि अभी भी होती है। मैंने यह कोशिश की है, और जवाब है, नहीं, ऐसा नहीं है।

    अन्य बात यह है कि इस बात का उल्लेख the multiprocessing docs से समस्या के संभावित कुंजी के रूप में किया गया था। JoinableQueue की की चर्चा करते हुए यह कहते हैं:

    ... अधूरा कार्य की संख्या की गणना करने के लिए इस्तेमाल कर सकते हैं सेमाफोर अंततः अतिप्रवाह एक अपवाद को ऊपर उठाने।


import multiprocessing 

class _ProcSTOP: 
    pass 

class Proc(multiprocessing.Process): 

    def __init__(self, pq, rq): 
     self._pq = pq 
     self._rq = rq 
     super().__init__() 
     print('++', self.name) 

    def run(self): 
     dat = self._pq.get() 

     while not dat is _ProcSTOP: 
#   self._rq.put(dat)  # uncomment me for deadlock 
      self._pq.task_done() 
      dat = self._pq.get() 

     self._pq.task_done() 
     print('==', self.name) 

    def __del__(self): 
     print('--', self.name) 

if __name__ == '__main__': 

    pq = multiprocessing.JoinableQueue() 
    rq = multiprocessing.JoinableQueue() 
    pool = [] 

    for i in range(4): 
     p = Proc(pq, rq) 
     p.start() 
     pool.append(p) 

    for i in range(10000): 
     pq.put(i) 

    pq.join() 

    for i in range(4): 
     pq.put(_ProcSTOP) 

    pq.join() 

    while len(pool) > 0: 
     print('??', pool) 
     pool.pop().join() # hangs here (if using rq) 

    print('** complete') 

नमूना उत्पादन, का उपयोग नहीं कर वापसी-कतार:

++ Proc-1 
++ Proc-2 
++ Proc-3 
++ Proc-4 
== Proc-4 
== Proc-3 
== Proc-1 
?? [<Proc(Proc-1, started)>, <Proc(Proc-2, started)>, <Proc(Proc-3, started)>, <Proc(Proc-4, started)>] 
== Proc-2 
?? [<Proc(Proc-1, stopped)>, <Proc(Proc-2, started)>, <Proc(Proc-3, stopped)>] 
-- Proc-3 
?? [<Proc(Proc-1, stopped)>, <Proc(Proc-2, started)>] 
-- Proc-2 
?? [<Proc(Proc-1, stopped)>] 
-- Proc-1 
** complete 
-- Proc-4 

नमूना उत्पादन, का उपयोग कर लौटने कतार:

++ Proc-1 
++ Proc-2 
++ Proc-3 
++ Proc-4 
== Proc-2 
== Proc-4 
== Proc-1 
?? [<Proc(Proc-1, started)>, <Proc(Proc-2, started)>, <Proc(Proc-3, started)>, <Proc(Proc-4, started)>] 
== Proc-3 
# here it hangs 
+0

संबंधित हो सकता है: http://bugs.python.org/issue8237 – jfs

+0

@ जेएफ। सेबेस्टियन। ऐसा हो सकता है लेकिन यह है कि यह कहते हुए किया जाना है कि यह ब्लॉक से पहले अपने सभी 'run' के return'' put' पर अवरोधित कर रही है, और 'put' केवल' run' भीतर तो मेरी 'put' की नहीं कर सकते हैं उत्पन्न कर रहा है लगता है अवरुद्ध होना – tjm

उत्तर

0
documentation से

:

चेतावनी

, जैसा कि ऊपर उल्लेख करता है, तो एक बच्चे की प्रक्रिया एक कतार पर आइटम डाल दिया है (और यह JoinableQueue.cancel_join_thread() का प्रयोग नहीं किया गया है), तो उस प्रक्रिया तब तक समाप्त नहीं होगा जब तक कि सभी बफर किए गए आइटम पाइप पर नहीं पहुंचे।

इसका मतलब यह है कि आप उस प्रक्रिया में शामिल होने की कोशिश जब तक आप सुनिश्चित करें कि सभी आइटम जो कतार पर डाल दिया है भस्म किया गया है एक गतिरोध मिल सकता है। इसी तरह, यदि बाल प्रक्रिया गैर-डिमनिक है तो माता-पिता प्रक्रिया अपने सभी गैर-डिमनिक बच्चों में शामिल होने का प्रयास करते समय बाहर निकल सकती है।

ध्यान दें कि एक कतार एक प्रबंधक का उपयोग कर इस मुद्दे को नहीं है बनाया। प्रोग्रामिंग दिशानिर्देश देखें।

तो जॉइनबलक्यूयू() एक पाइप का उपयोग करता है और बंद होने से पहले सभी डेटा फ्लश कर सकता है जब तक इंतजार करेगा।

दूसरी ओर एक Manager.Queue() वस्तु एक पूरी तरह से अलग दृष्टिकोण का उपयोग करता। प्रबंधक एक अलग प्रक्रिया है कि सभी डेटा तुरंत प्राप्त (और उसके स्मृति में संग्रहीत) चल रहे हैं।

प्रबंधक विभिन्न प्रक्रियाओं के बीच साझा किए जा सकने वाले डेटा को बनाने का एक तरीका प्रदान करते हैं। एक प्रबंधक ऑब्जेक्ट एक सर्वर प्रक्रिया को नियंत्रित करता है जो साझा वस्तुओं का प्रबंधन करता है। अन्य प्रक्रियाएं प्रॉक्सी का उपयोग करके साझा वस्तुओं तक पहुंच सकती हैं।

...

क़तार ([MAXSIZE]) एक साझा Queue.Queue वस्तु बना सकते हैं और इसके लिए एक प्रॉक्सी लौट आते हैं।

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