समवर्ती.फुट्स बनाम मल्टीप्रोसेसिंग इन पायथन 3


148

पायथन 3.2 ने समवर्ती फ्यूचर्स की शुरुआत की , जो पुराने थ्रेडिंग और मल्टीप्रोसेसिंग मॉड्यूल के कुछ उन्नत संयोजन प्रतीत होते हैं ।

पुराने मल्टीप्रोसेसिंग मॉड्यूल पर सीपीयू बाध्य कार्यों के लिए इसका उपयोग करने के फायदे और नुकसान क्या हैं?

यह लेख बताता है कि वे काम करना बहुत आसान है - क्या यह मामला है?

जवाबों:


145

मैं concurrent.futuresऔर अधिक "उन्नत" नहीं कहूंगा - यह एक सरल इंटरफ़ेस है जो बहुत समान रूप से काम करता है चाहे आप कई थ्रेड या कई प्रक्रियाओं का उपयोग अंतर्निहित समानांतरीकरण नौटंकी के रूप में करें।

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

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

संपादित करें: उदाहरण

यहां आपके द्वारा संदर्भित लेख में दिखाया गया अंतिम कोड है, लेकिन मैं इसे काम करने के लिए आवश्यक आयात विवरण जोड़ रहा हूं:

from concurrent.futures import ProcessPoolExecutor
def pool_factorizer_map(nums, nprocs):
    # Let the executor divide the work among processes by using 'map'.
    with ProcessPoolExecutor(max_workers=nprocs) as executor:
        return {num:factors for num, factors in
                                zip(nums,
                                    executor.map(factorize_naive, nums))}

यहाँ multiprocessingइसके बजाय का उपयोग कर बिल्कुल वही है :

import multiprocessing as mp
def mp_factorizer_map(nums, nprocs):
    with mp.Pool(nprocs) as pool:
        return {num:factors for num, factors in
                                zip(nums,
                                    pool.map(factorize_naive, nums))}

ध्यान दें कि multiprocessing.Poolसंदर्भ प्रबंधकों के रूप में वस्तुओं का उपयोग करने की क्षमता पायथन 3.3 में जोड़ी गई थी।

किसके साथ काम करना आसान है? LOL ;-) वे अनिवार्य रूप से समान हैं।

एक अंतर यह है कि Poolचीजों को करने के इतने अलग-अलग तरीकों का समर्थन करता है कि आप महसूस नहीं कर सकते कि यह कितना आसान हो सकता है जब तक कि आप सीखने की अवस्था में काफी ऊपर नहीं चढ़ते।

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


20
"आपको कई थ्रेड्स के बजाय कई प्रक्रियाओं की आवश्यकता होती है, जिसमें स्पीडअप प्राप्त करने का कोई मौका हो" बहुत कठोर है। यदि गति महत्वपूर्ण है; कोड पहले से ही C लाइब्रेरी का उपयोग कर सकता है और इसलिए यह GIL जैसे, regex, lxml, numpy जारी कर सकता है।
13

4
@JFSebastian, जो जोड़ने के लिए धन्यवाद - शायद मुझे " शुद्ध सीपीथॉन के तहत" कहना चाहिए था , लेकिन मुझे डर है कि जीआईएल पर चर्चा किए बिना यहां सच्चाई को समझाने का कोई छोटा रास्ता नहीं है।
टिम पीटर्स 16

2
और यह ध्यान देने योग्य है कि लंबे आईओ के साथ ऑपरेशन होने पर धागे विशेष रूप से उपयोगी और पर्याप्त हो सकते हैं।
कोट्रफा

9
@TimPeters कुछ मायनों में ProcessPoolExecutorवास्तव में अधिक विकल्प हैं Poolक्योंकि ProcessPoolExecutor.submitरिटर्न Futureऐसे उदाहरण हैं जो रद्द करने ( cancel) की अनुमति देते हैं , यह देखते हुए कि कौन सा अपवाद उठाया गया था ( exception), और गतिशील रूप से कॉलबैक को पूरा होने पर ( add_done_callback) कहा जाता है । इनमें से कोई भी सुविधा AsyncResultउदाहरणों के साथ उपलब्ध नहीं है Pool.apply_async। अन्य तरीकों से Poolकी वजह से अधिक विकल्प हैं initializer/ initargs, maxtasksperchildऔर contextमें Pool.__init__और भी बहुत कुछ तरीकों से अवगत कराया Poolउदाहरण।
अधिकतम

2
@ मोम, निश्चित, लेकिन ध्यान दें कि प्रश्न के बारे में नहीं था Pool, यह मॉड्यूल के बारे में था। Poolजो कुछ भी है उसका एक छोटा सा हिस्सा है multiprocessing, और डॉक्स में इतना नीचे है कि लोगों को यह महसूस करने में थोड़ा समय लगता है कि यह भी मौजूद है multiprocessing। यह विशेष रूप से उत्तर पर केंद्रित है Poolक्योंकि यह सभी लेख है जो ओपी उपयोग से जुड़ा हुआ है, और cfयह "काम करना बहुत आसान है" बस इस बारे में सच नहीं है कि लेख ने क्या चर्चा की। इसके अलावा, cfके as_completed()भी बहुत आसान हो सकता है।
टिम पीटर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.