क्या वास्तव में पायथन मल्टीप्लसिंग मॉड्यूल है .join () मेथड डूइंग?


110

पायथन मल्टीप्रोसेसिंग (एक PMOTW लेख से ) के बारे में सीखना और वास्तव में join()विधि क्या कर रही है पर कुछ स्पष्टीकरण पसंद करेंगे ।

2008 के एक पुराने ट्यूटोरियल में यह कहा गया है कि p.join()नीचे दिए गए कोड में कॉल के बिना , "बच्चे की प्रक्रिया बेकार बैठ जाएगी और समाप्त नहीं होगी, एक ज़ोंबी बनकर आपको मैन्युअल रूप से मारना होगा"।

from multiprocessing import Process

def say_hello(name='world'):
    print "Hello, %s" % name

p = Process(target=say_hello)
p.start()
p.join()

मैं का एक प्रिंटआउट जोड़ा PIDके रूप में अच्छी तरह से एक के रूप में time.sleepपरीक्षण करने के लिए और जहाँ तक मैं बता सकता है अपने आप ही, इस प्रक्रिया को समाप्त:

from multiprocessing import Process
import sys
import time

def say_hello(name='world'):
    print "Hello, %s" % name
    print 'Starting:', p.name, p.pid
    sys.stdout.flush()
    print 'Exiting :', p.name, p.pid
    sys.stdout.flush()
    time.sleep(20)

p = Process(target=say_hello)
p.start()
# no p.join()

20 सेकंड के भीतर:

936 ttys000    0:00.05 /Library/Frameworks/Python.framework/Versions/2.7/Reso
938 ttys000    0:00.00 /Library/Frameworks/Python.framework/Versions/2.7/Reso
947 ttys001    0:00.13 -bash

20 सेकंड के बाद:

947 ttys001    0:00.13 -bash

व्यवहार p.join()फ़ाइल के अंत में जोड़े गए के साथ ही है । वीक का पायथन मॉड्यूल मॉड्यूल की बहुत पठनीय व्याख्या प्रदान करता है ; "प्रतीक्षा करने के लिए जब तक कि कोई प्रक्रिया अपना काम पूरा न कर ले और बाहर निकल जाए, जॉइन () विधि का उपयोग करें।", लेकिन ऐसा लगता है कि कम से कम ओएस एक्स वैसे भी कर रहा था।

विधि के नाम के बारे में भी सोच रहा हूँ। क्या .join()विधि यहाँ कुछ भी कर रही है? क्या यह एक प्रक्रिया को समाप्त कर रहा है? या यह सिर्फ पायथन की मूल .join()विधि के साथ एक नाम साझा करता है ?


2
जहां तक ​​मुझे पता है, यह मुख्य धागा रखती है और बच्चे की प्रक्रिया पूरी होने तक इंतजार करती है और फिर मुख्य धागे में संसाधनों को शामिल करती है, ज्यादातर साफ बाहर निकलती है।
अभिषेकगर्ग

आह कि समझ में आता है। तो यह वास्तविक CPU, Memory resourcesमूल प्रक्रिया से अलग हो रहा है, फिर joinबच्चे की प्रक्रिया पूरी होने के बाद फिर से एड करें?
मिकीएलएल

हां, यही उसका काम है। इसलिए, यदि आप उन्हें वापस नहीं मिलाते हैं, जब बच्चे की प्रक्रिया समाप्त हो जाती है तो यह केवल एक दोषपूर्ण या मृत प्रक्रिया के रूप में होता है
abhishekgarg

@abhishekgarg यह सच नहीं है। मुख्य प्रक्रिया पूरी होने पर बच्चे की प्रक्रियाओं को अंतर्निहित रूप से शामिल किया जाएगा।
डानो

@ डानो, मैं अजगर भी सीख रहा हूं और मैंने अपने परीक्षणों में जो कुछ भी पाया, उसे साझा किया, मेरे परीक्षणों में मैंने कभी भी मुख्य प्रक्रिया समाप्त नहीं की थी, इसलिए शायद मैंने उन बच्चों की प्रक्रियाओं को दोषपूर्ण के रूप में देखा।
अभिषेकगर्ग

जवाबों:


125

join()विधि, जब साथ प्रयोग किया जाता threadingया multiprocessing, से संबंधित नहीं है str.join()- यह वास्तव में एक साथ कुछ भी श्रृंखलाबद्ध नहीं है। बल्कि, इसका मतलब सिर्फ यह है कि "इसके लिए प्रतीक्षा करें [धागा / प्रक्रिया] पूरा होने के लिए"। नाम joinका उपयोग किया जाता है क्योंकि multiprocessingमॉड्यूल का एपीआई मॉड्यूल के एपीआई के समान दिखता threadingहै, और threadingमॉड्यूल joinअपनी Threadवस्तु के लिए उपयोग करता है । join"प्रोग्रामिंग को पूरा करने के लिए एक धागे के लिए प्रतीक्षा करें" शब्द का उपयोग करना कई प्रोग्रामिंग भाषाओं में आम है, इसलिए पायथन ने इसे भी अपनाया।

अब, कारण आप कॉल के साथ और उसके बिना 20 सेकंड की देरी को देखते हैं join()क्योंकि डिफ़ॉल्ट रूप से, जब मुख्य प्रक्रिया बाहर निकलने के लिए तैयार होती है, तो यह join()सभी चल रहे multiprocessing.Processउदाहरणों पर अंतर्निहित रूप से कॉल करेगा । यह multiprocessingडॉक्स में उतना स्पष्ट रूप से नहीं बताया गया है जितना होना चाहिए, लेकिन यह प्रोग्रामिंग दिशानिर्देशों के खंड में उल्लिखित है :

यह भी याद रखें कि गैर-डेमोनिक प्रक्रियाएं स्वचालित रूप से शामिल हो जाएंगी।

प्रक्रिया शुरू करने से पहले आप daemonध्वज को सेट करके इस व्यवहार को ओवरराइड कर सकते हैं :ProcessTrue

p = Process(target=say_hello)
p.daemon = True
p.start()
# Both parent and child will exit here, since the main process has completed.

यदि आप ऐसा करते हैं, तो मुख्य प्रक्रिया पूरी होते ही बच्चे की प्रक्रिया समाप्त कर दी जाएगी :

डेमॉन

प्रक्रिया का डेमन ध्वज, एक बूलियन मान। इसे शुरू करने से पहले सेट किया जाना चाहिए () कहा जाता है।

प्रारंभिक मूल्य बनाने की प्रक्रिया से विरासत में मिला है।

जब कोई प्रक्रिया बाहर निकलती है, तो यह अपने सभी शैतानी बच्चे की प्रक्रियाओं को समाप्त करने का प्रयास करती है।


6
मैं समझ रहा था कि p.daemon=True"एक पृष्ठभूमि प्रक्रिया शुरू करना जो मुख्य कार्यक्रम को बाहर निकलने से अवरुद्ध किए बिना चलता है"। लेकिन अगर "मुख्य कार्यक्रम से बाहर निकलने से पहले डेमॉन प्रक्रिया स्वचालित रूप से समाप्त हो जाती है", तो वास्तव में इसका उपयोग क्या है?
मिकीएलएल

8
@MikeiLL मूल रूप से जब तक मूल प्रक्रिया चल रही है, तब तक आप पृष्ठभूमि में चल रहे कुछ भी चाहते हैं, लेकिन मुख्य कार्यक्रम से बाहर निकलने से पहले इसे इनायत से साफ करने की आवश्यकता नहीं है। शायद एक कार्यकर्ता प्रक्रिया जो सॉकेट या हार्डवेयर डिवाइस से डेटा पढ़ती है, और उस डेटा को एक कतार के माध्यम से माता-पिता को वापस खिलाती है या इसे किसी उद्देश्य के लिए पृष्ठभूमि में संसाधित करती है? सामान्य तौर पर मैं यह कहूंगा कि daemonicबाल प्रक्रिया का उपयोग करना बहुत सुरक्षित नहीं है, क्योंकि यह प्रक्रिया किसी भी खुले संसाधनों की सफाई के लिए बिना अनुमति के समाप्त होने वाली है।
डैनो

7
@ मायिकएलएल मुख्य प्रक्रिया से बाहर निकलने से पहले बच्चे को साफ करने और बाहर निकलने के लिए संकेत देना बेहतर होगा। आप सोच सकते हैं कि माता-पिता के बाहर निकलने पर डैमोनिक चाइल्ड प्रक्रिया को छोड़ने का कोई मतलब नहीं होगा, लेकिन ध्यान रखें कि multiprocessingएपीआई को threadingएपीआई को यथासंभव बारीकी से नकल करने के लिए डिज़ाइन किया गया है। threading.Threadजैसे ही मुख्य धागा बाहर निकलता है, डेमोनिक ऑब्जेक्ट समाप्त हो जाते हैं, इसलिए डायमोनिक multiprocesing.Processऑब्जेक्ट उसी तरह व्यवहार करते हैं।
डैनो

38

join()मुख्य प्रक्रिया के बिना , बच्चा प्रक्रिया करने से पहले मुख्य प्रक्रिया पूरी कर सकता है। मुझे यकीन नहीं है कि किन परिस्थितियों में ज़ोंबीवाद होता है।

इसका मुख्य उद्देश्य join()यह सुनिश्चित करना है कि मुख्य प्रक्रिया कुछ भी करने से पहले एक बच्चे की प्रक्रिया पूरी हो गई है जो कि बच्चे की प्रक्रिया के काम पर निर्भर करती है।

की व्युत्पत्ति join()यह है कि यह इसके विपरीत है fork, जो बाल प्रक्रियाओं के निर्माण के लिए यूनिक्स-परिवार ऑपरेटिंग सिस्टम में आम शब्द है। एक एकल प्रक्रिया "कांटे" कई में, फिर एक में "जुड़ती" है।


2
यह नाम का उपयोग करता है join()क्योंकि join()किसी threading.Threadऑब्जेक्ट को पूरा करने के लिए प्रतीक्षा करने के लिए उपयोग किया जाता है , और multiprocessingएपीआई का मतलब है threadingजितना संभव हो उतना एपीआई की नकल करना।
डानो

आपका दूसरा वक्तव्य उस समस्या को संबोधित करता है जो मैं वर्तमान परियोजना में काम कर रहा हूं।
मिकीएलएल

मैं उस हिस्से को समझता हूं जहां मुख्य धागा उप-प्रक्रिया के पूरा होने की प्रतीक्षा करता है, लेकिन क्या उस तरह की हार असिंक्रोनस निष्पादन के उद्देश्य को नहीं हराती है? क्या इसे निष्पादन को समाप्त करना नहीं है, स्वतंत्र रूप से (उप-कार्य या प्रक्रिया)?
अपूर्वा कुंकुलोल

1
@ApurvaKunkulol इस बात पर निर्भर करता है कि आप इसका उपयोग कैसे कर रहे हैं, लेकिन join()इस मामले में जरूरत होती है जहां मुख्य सूत्र को उप-थ्रेड्स के कार्य के परिणामों की आवश्यकता होती है। उदाहरण के लिए, यदि आप कुछ प्रदान कर रहे हैं और 4 उपप्रकारों में से प्रत्येक को अंतिम छवि का 1/4 असाइन करते हैं, और जब यह पूरा हो जाता है तो पूरी छवि प्रदर्शित करना चाहते हैं।
रसेल बोरोगोव

@RussellBorogove आह! मैं समझ गया। फिर अतुल्यकालिक गतिविधि का अर्थ यहां थोड़ा अलग है। इसका मतलब केवल इस तथ्य से होना चाहिए कि उप-प्रक्रियाएं मुख्य धागे के साथ अपने कार्यों को एक साथ करने के लिए होती हैं, जबकि मुख्य धागा भी उप-प्रक्रियाओं पर केवल मूर्खतापूर्ण प्रतीक्षा के बजाय काम करता है।
अपूर्वा कुंकुलोल

12

मैं विस्तार से नहीं joinबताता कि क्या करता है, लेकिन यहाँ व्युत्पत्ति और इसके पीछे का अंतर्ज्ञान है, जो आपको इसके अर्थ को आसानी से याद रखने में मदद करनी चाहिए।

विचार यह है कि निष्पादन " कांटे " कई प्रक्रियाओं में है जिसमें से एक मास्टर है, बाकी श्रमिक (या "दास")। जब श्रमिकों को किया जाता है, तो वे मास्टर से "जुड़ते हैं" ताकि धारावाहिक निष्पादन फिर से शुरू हो सके।

joinविधि एक कार्यकर्ता शामिल होने के लिए के लिए इंतजार करना मास्टर प्रक्रिया का कारण बनता है। विधि को बेहतर रूप से "प्रतीक्षा" कहा जा सकता है, क्योंकि यह वास्तविक व्यवहार है जो इसे मास्टर में कारण बनता है (और यही वह है जिसे पोसिक्स में कहा जाता है, हालांकि पोसिक्स थ्रेड इसे "जॉइन" भी कहते हैं)। केवल जुड़ने से धागे का प्रभाव ठीक से सहयोग करने के रूप में होता है, यह ऐसा कुछ नहीं है जो मास्टर करता है

1963 से मल्टीप्रोसेसिंग में "फोर्क" और "जॉइन" नामों को इस अर्थ के साथ इस्तेमाल किया गया है ।


तो एक तरह से इस शब्द joinका उपयोग पूर्ववर्ती के संदर्भ में किया जा सकता है, जैसा कि अन्य तरीके से किया गया है।
मिकीएलएल

1
यह संभावना नहीं है कि बहुसंकेतन में उपयोग से प्राप्त संघनन में उपयोग; बल्कि दोनों इंद्रियाँ शब्द के सादे-अंग्रेज़ी अर्थ से अलग-अलग हैं।
रसेल बोरोगोव

2

join()कार्यकर्ता प्रक्रियाओं से बाहर निकलने के लिए प्रतीक्षा करने के लिए उपयोग किया जाता है। उपयोग करने से पहले close()या कॉल करना चाहिए ।terminate()join()

जैसे @Russell में शामिल होने का उल्लेख कांटा के विपरीत है (जो उप-प्रक्रियाओं को बनाता है)।

दौड़ने में शामिल होने के लिए आपको दौड़ना close()होगा जो किसी भी अधिक कार्य को पूल में जमा करने से रोकेगा और सभी कार्यों के पूरा होने पर बाहर निकल जाएगा। वैकल्पिक रूप से, terminate()सभी कर्मचारी प्रक्रियाओं को तुरंत रोककर रनिंग बस बाहर निकल जाएगी।

"the child process will sit idle and not terminate, becoming a zombie you must manually kill" यह तब संभव है जब मुख्य (माता-पिता) प्रक्रिया से बाहर निकल जाता है, लेकिन बच्चे की प्रक्रिया अभी भी चल रही है और एक बार पूरी हो जाने के बाद इसकी निकास प्रक्रिया को वापस करने के लिए कोई मूल प्रक्रिया नहीं है।


2

join()कॉल सुनिश्चित करें कि आपके कोड के बाद लाइनों सभी बहु प्रक्रियाओं को पूरा कर रहे हैं इससे पहले कि कहा जाता है नहीं कर रहे हैं।

उदाहरण के लिए, बिना join(), निम्नलिखित कोड restart_program()प्रक्रियाओं के खत्म होने से पहले भी कॉल करेगा , जो एसिंक्रोनस के समान है और वह नहीं है जो हम चाहते हैं (आप कोशिश कर सकते हैं):

num_processes = 5

for i in range(num_processes):
    p = multiprocessing.Process(target=calculate_stuff, args=(i,))
    p.start()
    processes.append(p)
for p in processes:
    p.join() # call to ensure subsequent line (e.g. restart_program) 
             # is not called until all processes finish

restart_program()

0

तब तक प्रतीक्षा करने के लिए जब तक कि कोई प्रक्रिया अपना काम पूरा न कर ले और बाहर निकल जाए, जॉइन () विधि का उपयोग करें।

तथा

नोट पृष्ठभूमि मशीनरी को समाप्ति को प्रतिबिंबित करने के लिए ऑब्जेक्ट की स्थिति को अपडेट करने के लिए समय देने के लिए इसे समाप्त करने के बाद प्रक्रिया में शामिल होना आवश्यक है।

यह एक अच्छा उदाहरण है जिसने मुझे इसे समझने में मदद की: यहाँ

एक बात जो मैंने व्यक्तिगत रूप से देखी, वह थी मेरी मुख्य प्रक्रिया को तब तक रोक दिया गया जब तक कि बच्चे ने ज्वाइन () पद्धति का उपयोग करके अपनी प्रक्रिया पूरी नहीं कर ली, जिसने मुझे multiprocessing.Process()पहली जगह का उपयोग करने की बात को हरा दिया ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.