पायथन में सबप्रोसेस, मल्टीप्रोसेसिंग और थ्रेड के बीच निर्णय लेना?


110

मैं अपने पायथन प्रोग्राम को समानांतर करना चाहता हूं ताकि यह मशीन पर कई प्रोसेसर का उपयोग कर सके जो इसे चलाता है। मेरा समानांतरकरण बहुत सरल है, जिसमें प्रोग्राम के सभी समानांतर "थ्रेड्स" स्वतंत्र हैं और अलग-अलग फ़ाइलों के लिए अपना आउटपुट लिखते हैं। मुझे जानकारी का आदान-प्रदान करने के लिए थ्रेड्स की आवश्यकता नहीं है, लेकिन यह जरूरी है कि मुझे पता है कि जब थ्रेड खत्म हो जाते हैं, क्योंकि मेरी पाइपलाइन के कुछ चरण उनके आउटपुट पर निर्भर करते हैं।

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

इस पर कोई विचार? मैं सबसे सरल समाधान चाहता हूं जो पोर्टेबल हो।


संबंधित: stackoverflow.com/questions/1743293/… (मेरे जवाब को यह देखने के लिए कि धागे शुद्ध-पायथन कोड के लिए गैर-स्टार्टर क्यों हैं)

1
"कोई भी पायथन संस्करण" FAR बहुत अस्पष्ट है। पायथन 2.3? 1.x? 3.x? यह केवल संतुष्ट करने के लिए एक असंभव स्थिति है।
detly

जवाबों:


64

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

subprocessमॉड्यूल भी आप कई प्रक्रियाओं शुरू करने की अनुमति होगी, लेकिन मैंने पाया यह कम नई बहु मॉड्यूल से उपयोग करने के लिए सुविधाजनक हो।

थ्रेड्स कुख्यात सूक्ष्म रूप से हैं, और, सीपीथॉन के साथ, आप अक्सर एक कोर तक सीमित होते हैं, उनके साथ (भले ही, जैसा कि टिप्पणियों में से एक में नोट किया गया है, ग्लोबल इंटरप्रेटर लॉक (जीआईएल) पायथन कोड नामक सी कोड में जारी किया जा सकता है) ।

मेरा मानना ​​है कि आपके द्वारा उद्धृत तीन मॉड्यूल के अधिकांश कार्यों का उपयोग प्लेटफ़ॉर्म-स्वतंत्र तरीके से किया जा सकता है। पोर्टेबिलिटी की ओर, ध्यान दें कि multiprocessingकेवल मानक में आता है पायथन 2.6 (पायथन के कुछ पुराने संस्करणों के लिए एक संस्करण मौजूद है, हालांकि)। लेकिन यह एक महान मॉड्यूल है!


1
एक असाइनमेंट के लिए, मैंने सिर्फ "मल्टीप्रोसेसिंग" मॉड्यूल और उसके पूल का उपयोग किया। केक का टुकड़ा !
kmonsoor

क्या अजवाइन जैसी चीज भी विचाराधीन है? क्यों है या नहीं है?
user3245268 18

जहां तक ​​मैं बता सकता हूं कि सेलेरी अधिक शामिल है (आपको कुछ संदेश ब्रोकर को स्थापित करना होगा), लेकिन यह एक विकल्प है जिसे संभवतः हाथ पर समस्या के आधार पर माना जाना चाहिए।
एरिक ओ लेबिगॉट

186

मेरे लिए यह वास्तव में बहुत सरल है:

उपप्रक्रिया विकल्प:

subprocessहै अन्य निष्पादनयोग्य चलाने के लिए --- यह मूल रूप से एक आवरण के आसपास है os.fork()और os.execve()वैकल्पिक पाइपलाइन के लिए कुछ समर्थन के साथ (करने के लिए और subprocesses से पीआइपीईएस की स्थापना। जाहिर है आप कर सकते थे अन्य अंतर-प्रक्रिया संचार (आईपीसी) इस तरह के सॉकेट के रूप में तंत्र, या Posix या SysV ने साझा की गई मेमोरी। लेकिन आप जिन भी इंटरफेस और आईपीसी चैनलों को कॉल कर रहे हैं, उन कार्यक्रमों के लिए सीमित हैं।

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

हालांकि एक व्यक्ति सैकड़ों उपप्रकारों को फैला सकता है और उन्हें प्रदूषित कर सकता है। मेरा अपना निजी पसंदीदा उपयोगिता वर्ग ठीक यही करता है। मॉड्यूल का सबसे बड़ा नुकसान यह subprocessहै कि I / O समर्थन आमतौर पर अवरुद्ध होता है। PEP-3145 का एक मसौदा तैयार करना है जो कि भविष्य के पायथन 3.x के कुछ संस्करण और एक वैकल्पिक asyncproc (चेतावनी जो डाउनलोड करने के लिए सही दिशा में ले जाता है, न कि किसी भी प्रकार के दस्तावेज़ और न ही README)। मैंने यह भी पाया है कि fcntlअपने PopenPIPE फ़ाइल डिस्क्रिप्टर को सीधे आयात और हेरफेर करना अपेक्षाकृत आसान है --- हालांकि मुझे नहीं पता कि यह गैर-यूनिक्स प्लेटफार्मों के लिए पोर्टेबल है या नहीं।

(अपडेट: for अगस्त २०१ ९: पायनियर ३ सपोर्ट फॉर एनिनिको सबप्रोसेस: एसिंसीओ सबप्रोसेस )

subprocess आपके पास लगभग कोई ईवेंट हैंडलिंग सपोर्ट नहीं है ... हालाँकि आप signalमॉड्यूल और सादे पुराने स्कूल UNIX / Linux सिग्नल का उपयोग कर सकते हैं --- अपनी प्रक्रियाओं को धीरे से मार सकते हैं, जैसे कि वे थे।

बहु विकल्प:

multiprocessingहै अपने मौजूदा (अजगर) कोड के भीतर कार्यों को चलाने के लिए प्रक्रियाओं के इस परिवार के बीच और अधिक लचीला संचार के लिए समर्थन के साथ। विशेष रूप से जहां संभव हो multiprocessingमॉड्यूल के Queueऑब्जेक्ट्स के आसपास अपना आईपीसी बनाना सबसे अच्छा है, लेकिन आप Eventऑब्जेक्ट्स और विभिन्न अन्य सुविधाओं का उपयोग भी कर सकते हैं (जिनमें से कुछ, संभवतः mmapउन प्लेटफार्मों पर समर्थन के आसपास निर्मित होते हैं जहां यह समर्थन पर्याप्त है)।

पाइथन के multiprocessingमॉड्यूल का उद्देश्य इंटरफेस और फीचर्स प्रदान करना है जो कि GIL (ग्लोबल इंटरप्रेटर लॉक) के बावजूद CPython को कई सीपीयू / कोर के बीच अपने प्रसंस्करण को स्केल करने की अनुमति देने के समान हैं threading। यह आपके ओएस कर्नेल के डेवलपर्स द्वारा किए गए सभी बढ़िया अनाज एसएमपी लॉकिंग और सुसंगत प्रयास का लाभ उठाता है।

सूत्रण विकल्प:

threadingहै अनुप्रयोग हैं जिनमें से एक काफी संकीर्ण सीमा के लिए आई / ओ बाध्य और बेहद कम विलंबता से जो लाभ और धागा स्विचिंग की भूमि के ऊपर स्विचन (साझा कोर स्मृति के साथ) बनाम प्रक्रिया (कई सीपीयू कोर में बड़े पैमाने की जरूरत नहीं है) / संदर्भ स्विचिंग। लिनक्स पर यह लगभग खाली सेट है (लिनक्स प्रक्रिया स्विच बार इसके थ्रेड-स्विच के बेहद करीब है)।

threadingपाइथन में दो बड़े नुकसान से ग्रस्त है ।

एक, ज़ाहिर है, कार्यान्वयन विशिष्ट है --- ज्यादातर सीपीथॉन को प्रभावित कर रहा है। यही GIL है। अधिकांश भाग के लिए, अधिकांश सीपीथॉन कार्यक्रमों को दो से अधिक सीपीयू (कोर) की उपलब्धता से लाभ नहीं होगा और अक्सर प्रदर्शन जीआईएल लॉकिंग विवाद से ग्रस्त होंगे ।

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

तुलना करके multiprocessingमॉडल प्रत्येक प्रक्रिया को अपनी मेमोरी, फ़ाइल डिस्क्रिप्टर आदि देता है। उनमें से किसी एक में क्रैश या अनहेल्डेड अपवाद केवल उस संसाधन को मार देगा और बच्चे के गायब होने या सिबलिंग प्रक्रिया को मजबूती से निपटाना डिबगिंग, अलगाव से काफी आसान हो सकता है। और धागे में समान मुद्दों के आसपास फिक्सिंग या काम करना।

  • (नोट: threadingप्रमुख Python सिस्टम के साथ, जैसे कि NumPy , का उपयोग GIL विवाद से काफी कम हो सकता है, जो आपके अधिकांश Python कोड से होगा। ऐसा इसलिए है क्योंकि उन्हें विशेष रूप से ऐसा करने के लिए इंजीनियर किया गया है; NumPy का मूल / बाइनरी भाग; उदाहरण के लिए, GIL को तब जारी करेगा जब वह सुरक्षित हो)।

मुड़ विकल्प:

यह भी ध्यान देने योग्य है कि ट्विस्टेड अभी तक एक और विकल्प प्रदान करता है जो समझने के लिए सुरुचिपूर्ण और बहुत चुनौतीपूर्ण दोनों है । मूल रूप से, उस बिंदु पर सरलीकरण के जोखिम पर, जहां ट्विस्टेड के प्रशंसक मेरे घर को पिचफॉर्क और टॉर्च के साथ तूफान कर सकते हैं, ट्विस्टेड किसी भी (एकल) प्रक्रिया के भीतर घटना-संचालित सहकारी मल्टी-टास्किंग प्रदान करता है।

यह समझने के लिए कि यह कैसे संभव है कि किसी को select()(जिसे चुनिंदा ( या पोल या ) या इसी तरह के OS OS कॉल के आसपास बनाया जा सकता है ) की विशेषताओं के बारे में पढ़ना चाहिए । मूल रूप से यह सब फ़ाइल विवरणकों या कुछ समय की सूची पर किसी भी गतिविधि को लंबित करने के लिए ओएस के अनुरोध को करने की क्षमता से प्रेरित है।

इन कॉलों में से प्रत्येक के प्रति जागृति select()एक घटना है --- या तो किसी संख्या में सॉकेट या फ़ाइल डिस्क्रिप्टर पर उपलब्ध इनपुट (पठनीय), या बफ़रिंग स्पेस कुछ अन्य (लिखने योग्य) डिस्क्रिप्टर या सॉकेट्स पर उपलब्ध हो रहा है, कुछ असाधारण स्थिति (टीसीपी) आउट-ऑफ-बैंड PUSH'd पैकेट, उदाहरण के लिए), या टाइमटाइम।

इस प्रकार मुड़ प्रोग्रामिंग मॉडल को इन घटनाओं को संभालने के बाद बनाया गया है, जिसके परिणामस्वरूप "मुख्य" हैंडलर पर लूपिंग की जाती है, जिससे यह आपके हैंडलर को घटनाओं को भेज सकता है।

मैं व्यक्तिगत रूप से नाम के बारे में सोच, मुड़ प्रोग्रामिंग मॉडल की विचारोत्तेजक ... के बाद से समस्या के लिए अपने दृष्टिकोण होना चाहिए के रूप में, कुछ अर्थों में, "मुड़" अंदर बाहर। इनपुट डेटा और आउटपुट या परिणाम पर संचालन की एक श्रृंखला के रूप में अपने कार्यक्रम की कल्पना करने के बजाय, आप अपना कार्यक्रम एक सेवा या डेमॉन के रूप में लिख रहे हैं और यह परिभाषित कर रहे हैं कि यह विभिन्न घटनाओं पर कैसे प्रतिक्रिया करता है। (वास्तव में एक मुड़ कार्यक्रम का मुख्य "मुख्य लूप" है (आमतौर पर? हमेशा?) ए reactor()

मुड़ उपयोग करने के लिए एक प्रमुख चुनौती कार्यक्रम चालित मॉडल के आसपास अपने मन घुमा और किसी भी वर्ग पुस्तकालयों या उपकरणकिटें जो करने के लिए लिखा नहीं कर रहे हैं के उपयोग को छोड़कर शामिल मुड़ ढांचे के भीतर सहयोग। यही कारण है कि ट्विस्टेड SSH प्रोटोकॉल हैंडलिंग के लिए, शापों के लिए, और अपने स्वयं के उपप्रकार / पोपेन कार्यों के लिए, और कई अन्य मॉड्यूल और प्रोटोकॉल हैंडलर की आपूर्ति करता है, जो पहले ब्लश में पायथन मानक पुस्तकालयों में चीजों की नकल करते प्रतीत होते हैं।

मुझे लगता है कि यह एक वैचारिक स्तर पर मुड़ समझने के लिए उपयोगी है, भले ही आप इसे इस्तेमाल करने का इरादा न करें। यह आपके थ्रेडिंग, मल्टीप्रोसेसिंग और यहां तक ​​कि सबप्रोसेस हैंडलिंग और साथ ही आपके द्वारा किए गए किसी भी वितरित प्रसंस्करण में प्रदर्शन, विवाद और घटना से निपटने में अंतर्दृष्टि दे सकता है।

( नोट: 3.x शामिल कर रहे हैं अजगर के नए संस्करण asyncio ) (अतुल्यकालिक मैं / हे जैसे सुविधाओं async डीईएफ़ , @ async.coroutine डेकोरेटर, और इंतजार कीवर्ड और उपज भविष्य से समर्थन इन सभी के लगभग समान ही हैं। एक प्रक्रिया (सहकारी मल्टीटास्किंग) परिप्रेक्ष्य से मुड़ )। (पायथन 3 के लिए मुड़ समर्थन की वर्तमान स्थिति के लिए, देखें: https://twistedmatrix.com/documents/current/core/howto/python3.html )

वितरित विकल्प:

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

रेडिस के आसपास वितरित प्रसंस्करण का निर्माण करना लगभग तुच्छ है । संपूर्ण कुंजी स्टोर का उपयोग कार्य इकाइयों और परिणामों को संग्रहीत करने के लिए किया जा सकता है, Redis LISTs का उपयोग Queue()ऑब्जेक्ट के रूप में किया जा सकता है , और PUB / SUB समर्थन का उपयोग समान Eventहैंडलिंग के लिए किया जा सकता है । आप अपनी कुंजियों का उपयोग कर सकते हैं और मूल्यों का उपयोग कर सकते हैं, Redis उदाहरणों के एक ढीले क्लस्टर में प्रतिकृति, टोपोलॉजी और हैश-टोकन मैपिंग को संग्रहीत करने के लिए अपने श्रमिकों के समन्वय के लिए किसी भी एक उदाहरण की क्षमता से परे स्केलिंग के लिए लगातार हैशिंग और असफलता प्रदान करने के लिए। और मार्शलिंग डेटा (मसालेदार, JSON, BSON, या YAML) उनमें से।

बेशक आप एक बड़े पैमाने और Redis चारों ओर और अधिक परिष्कृत समाधान का निर्माण करने शुरू के रूप में आप फिर से लागू करने विशेषताएं है कि पहले से ही प्रयोग, सुलझाई जा सकती से कई अजवाइन , अपाचे स्पार्क और Hadoop , Zookeeper , etcd , कैसेंड्रा और इतने पर। उन सभी के पास अपनी सेवाओं के लिए पायथन पहुंच के मॉड्यूल हैं।

[अद्यतन: यदि आप वितरित सिस्टम में कम्प्यूटेशनल रूप से गहन के लिए पायथन पर विचार कर रहे हैं, तो विचार के लिए संसाधनों के एक जोड़े: आईपीथॉन समानांतर और PySpark । जबकि ये सामान्य उद्देश्य वितरित कंप्यूटिंग सिस्टम हैं, वे विशेष रूप से सुलभ और लोकप्रिय सबसिस्टम डेटा साइंस और एनालिटिक्स] हैं।

निष्कर्ष

आपके पास पायथन के लिए प्रसंस्करण विकल्पों का सरगम ​​है, एकल थ्रेड से, उप-प्रक्रियाओं के लिए सरल तुल्यकालिक कॉल के साथ, मतदान उपप्रकारों के पूल, थ्रेडेड और मल्टीप्रोसेसिंग, इवेंट-संचालित सहकारी मल्टी-टास्किंग, और वितरित प्रसंस्करण के लिए।


1
हालांकि वर्गों / OOP के साथ बहुसंकेतन का उपयोग करना कठिन है।
तजोरीमेरी

2
@Tjorriemorrie: मैं अनुमान लगाने जा रहा हूं कि आपका मतलब है कि वस्तुओं के उदाहरणों के लिए विधि कॉल को भेजना कठिन है जो अन्य प्रक्रियाओं में हो सकता है। मेरा सुझाव है कि यह वही समस्या है जो आपको थ्रेड्स के साथ होगी, लेकिन अधिक आसानी से दिखाई देती है (बजाय नाजुक और दौड़ की स्थिति को अस्पष्ट करने के लिए)। मुझे लगता है कि अनुशंसित दृष्टिकोण कतार वस्तुओं के माध्यम से होने वाले ऐसे सभी प्रेषण के लिए व्यवस्था करने के लिए होगा, जो एकल थ्रेडेड, बहु-थ्रेडेड और संपूर्ण प्रक्रियाओं में काम करते हैं। (कुछ रेडिस या अजवाइन कतार कार्यान्वयन के साथ, नोड्स के एक समूह में भी)
जिम डेनिस

2
यह एक बहुत अच्छा जवाब है। काश, यह पायथन 3 डॉक्स में कंसीडर के परिचय में होता।
रूट -11

1
@ रूट -11 आप दस्तावेज़ के रखवालों के सामने इसका स्वागत करते हैं; मैंने इसे मुफ्त उपयोग के लिए यहाँ प्रकाशित किया है। आप और वे इसका उपयोग करने के लिए स्वागत करते हैं, पूरे या भागों में।
जिम डेनिस

"मेरे लिए यह वास्तव में बहुत सरल है:" इसे प्यार करो। बहुत बहुत धन्यवाद
जेरोम

5

इसी तरह के एक मामले में मैंने अलग-अलग प्रक्रियाओं और थोड़े से आवश्यक संचार गर्त नेटवर्क सॉकेट का विकल्प चुना। यह बहुत पोर्टेबल है और अजगर का उपयोग करने के लिए काफी सरल है, लेकिन शायद सरल नहीं है (मेरे मामले में मेरे पास एक और बाधा भी थी: सी ++ में लिखित अन्य प्रक्रियाओं के साथ संचार)।

आपके मामले में मैं शायद मल्टीप्रोसेस के लिए जाऊंगा, जैसे कि अजगर धागे, कम से कम जब सीपीथॉन का उपयोग करते हैं, तो असली धागे नहीं होते हैं। ठीक है, वे मूल सिस्टम थ्रेड हैं लेकिन पायथन से बुलाए गए सी मॉड्यूल जीआईएल को जारी नहीं कर सकते हैं या अन्य थ्रेड्स को अवरुद्ध कोड कहते समय चलने दे सकते हैं।


4

CPython में कई प्रोसेसर का उपयोग करने के लिए आपकी एकमात्र पसंद multiprocessingमॉड्यूल है। CPython इन्टर्नल्स ( GIL ) पर एक लॉक रखता है जो समानांतर में काम करने के लिए अन्य cpus पर थ्रेड्स को रोकता है। multiprocessingमॉड्यूल (जैसे नई प्रक्रियाओं बनाता है subprocess) और उन दोनों के बीच संचार का प्रबंधन करता है।


5
यह काफी हद तक सही नहीं है, AFAIK आप C API का उपयोग करके GIL को जारी कर सकते हैं, और Python के अन्य कार्यान्वयन जैसे कि IronPython या Jython हैं जो ऐसी सीमाओं से ग्रस्त नहीं हैं। मैं हालांकि नीचे नहीं था।
बास्टियन लेओनार्ड

1

शेल आउट करें और यूनिक्स को अपना काम करने दें:

सबप्रोसेस को लपेटने के लिए iterpipes का उपयोग करें और फिर:

टेड ज़िबा की साइट से

INPUTS_FROM_YOU | xargs -n1 -0 -P NUM ./process #NUM समानांतर प्रक्रियाएँ

या

गन्न समानांतर भी काम करेगा

आप GIL के साथ हैंगआउट करते हैं, जब आप अपने मल्टीकोर काम करने के लिए बैकरूम लड़कों को बाहर भेजते हैं।


6
"पोर्टेबिलिटी महत्वपूर्ण है, इस तरह मैं मैक, लिनक्स और विंडोज पर किसी भी पायथन संस्करण पर चलना चाहूंगा।"
सेप

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