multiprocessing.Pool: कब उपयोग करें, apply_async या मैप करें?


290

मैं के साथ के लिए उपयोग-मामले स्पष्ट उदाहरण नहीं देखा है Pool.apply , Pool.apply_async और Pool.map । मैं मुख्य रूप से उपयोग कर रहा हूं Pool.map; दूसरों के फायदे क्या हैं?

जवाबों:


424

पायथन के पुराने दिनों में वापस, मनमाने ढंग से तर्कों के साथ एक समारोह को बुलाने के लिए, आप उपयोग करेंगे apply:

apply(f,args,kwargs)

applyअभी भी Python2.7 में मौजूद है, हालांकि Python3 में नहीं है, और आमतौर पर इसका उपयोग नहीं किया जाता है। आजकल,

f(*args,**kwargs)

पसंद है। multiprocessing.Poolमॉड्यूल एक समान इंटरफेस प्रदान करने की कोशिश करता है।

Pool.applyपायथन की तरह है apply, सिवाय इसके कि फ़ंक्शन कॉल एक अलग प्रक्रिया में किया जाता है। Pool.applyफ़ंक्शन पूरा होने तक ब्लॉक करता है।

Pool.apply_asyncपायथन के बिल्ट-इन की तरह भी है apply, सिवाय इसके कि कॉल रिजल्ट के इंतजार के बजाय तुरंत लौट आए। कोई AsyncResultवस्तु लौटा दी जाती है। आप get()फ़ंक्शन कॉल के परिणाम को प्राप्त करने के लिए इसकी विधि कहते हैं। get()समारोह जब तक विधि ब्लॉक पूरा हो गया है। इस प्रकार, pool.apply(func, args, kwargs)के बराबर है pool.apply_async(func, args, kwargs).get()

इसके विपरीत Pool.apply, Pool.apply_asyncविधि में एक कॉलबैक भी होता है, जिसे यदि आपूर्ति की जाती है, तो फ़ंक्शन पूरा होने पर कॉल किया जाता है। इसका उपयोग कॉल करने के बजाय किया जा सकता है get()

उदाहरण के लिए:

import multiprocessing as mp
import time

def foo_pool(x):
    time.sleep(2)
    return x*x

result_list = []
def log_result(result):
    # This is called whenever foo_pool(i) returns a result.
    # result_list is modified only by the main process, not the pool workers.
    result_list.append(result)

def apply_async_with_callback():
    pool = mp.Pool()
    for i in range(10):
        pool.apply_async(foo_pool, args = (i, ), callback = log_result)
    pool.close()
    pool.join()
    print(result_list)

if __name__ == '__main__':
    apply_async_with_callback()

इस तरह के रूप में एक परिणाम मिल सकता है

[1, 0, 4, 9, 25, 16, 49, 36, 81, 64]

नोटिस, इसके विपरीत pool.map, परिणामों का क्रम उस क्रम के अनुरूप नहीं हो सकता है जिसमें pool.apply_asyncकॉल किए गए थे।


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

यदि आप चाहते हैं कि कार्यकर्ता कई प्रक्रियाओं को असिंक्रोनस रूप से करने के लिए पूल का उपयोग करें Pool.apply_asyncआदेश परिणामों के लिए कॉल के आदेश के रूप में ही होने की गारंटी नहीं है Pool.apply_async

ध्यान दें कि आप कई अलग-अलग फ़ंक्शन के साथ कॉल कर सकते हैं Pool.apply_async(सभी कॉल को एक ही फ़ंक्शन का उपयोग करने की आवश्यकता नहीं है)।

इसके विपरीत, Pool.mapएक ही फ़ंक्शन कई तर्कों पर लागू होता है। हालांकि, इसके विपरीत Pool.apply_async, परिणाम तर्कों के क्रम के अनुसार एक क्रम में वापस आ जाते हैं।


11
विंडोज पर if __name__=="__main__"पहले होना चाहिए apply_async_with_callback()?
jfs

3
बहुत बहुत धन्यवाद। map_async के बारे में कैसे?
फियो अर्कार Lwin

38
मल्टीप्रोसेसिंग / पूल-थ्रू के अंदर देखें और आप देखेंगे कि Pool.map(func,iterable)यह बराबर है Pool.map_async(func,iterable).get()। तो बीच के रिश्ते Pool.mapऔर Pool.map_asyncके समान है Pool.applyऔर Pool.apply_asyncasyncजबकि गैर आदेश, तुरंत लौट asyncआदेशों को ब्लॉक। asyncआदेशों भी एक कॉलबैक है।
अनटुब

7
उपयोग करने के बीच निर्णय लेना Pool.mapऔर तय करना के Pool.applyसमान है कि कब उपयोग करना है mapया applyपायथन में है। आप बस उस टूल का उपयोग करते हैं जो काम को फिट करता है। asyncऔर गैर- asyncसंस्करण का उपयोग करने के बीच निर्णय लेना इस बात पर निर्भर करता है कि क्या आप कॉल को वर्तमान प्रक्रिया को ब्लॉक करना चाहते हैं और / या यदि आप कॉलबैक का उपयोग करना चाहते हैं।
अनटुब

6
@falsePockets: हाँ। प्रत्येक कॉल apply_asyncएक ApplyResultवस्तु को वापस करने के लिए । कॉलिंग कि ApplyResultकी getविधि संबद्ध फ़ंक्शन द्वारा दिया गया मूल्य (या बढ़ाने वापस आ जाएगी mp.TimeoutError, तो कॉल समय बाहर।) तो अगर आप डाल ApplyResultएक आदेश दिया सूची में, तो उनके फोन करने getके तरीकों उसी क्रम में परिणाम देगा। आप pool.mapहालांकि इस स्थिति में उपयोग कर सकते हैं ।
unutbu

75

applyबनाम के बारे में map:

pool.apply(f, args): fकेवल पूल के श्रमिकों में से एक में निष्पादित किया जाता है। तो पूल में से एक प्रक्रिया चलेगी f(args)

pool.map(f, iterable): यह विधि पुनरावृत्ति को कई संख्या में काट देती है जिसे यह प्रक्रिया पूल में अलग-अलग कार्यों के रूप में जमा करता है। तो आप पूल में सभी प्रक्रियाओं का लाभ उठाते हैं।


4
क्या होगा अगर
चलने

हम्म ... अच्छा सवाल है। ईमानदार होने के लिए मैंने कभी भी जनरेटर के साथ पूल का उपयोग नहीं किया है, लेकिन यह धागा सहायक हो सकता है: stackoverflow.com/questions/5318936/…
kakhkAtion

@kakhktion लागू करने के बारे में, यदि केवल एक कार्यकर्ता ही कार्य निष्पादित करता है, तो बाकी श्रमिक क्या करते हैं? क्या मुझे कई बार अप्लाई करने के लिए कॉल करना होगा ताकि बाकी वर्कर्स कोई टास्क कर सकें?
मूंदड़ा

3
सच। यदि आप श्रमिकों को अतुल्यकालिक रूप से दोपहर का भोजन करना चाहते हैं, तो पूल पर भी नज़र डालें। जब तक परिणाम तैयार नहीं हो जाता है, तब तक पूल_एप्पली ब्लॉक होता है, इसलिए apply_async () समानांतर में काम करने के लिए बेहतर अनुकूल है "
kakhkAtion

1
क्या होता है जब मेरे पास 4 प्रक्रियाएं होती हैं लेकिन apply_async()8 बार कॉल किया जाता है? क्या यह स्वचालित रूप से एक कतार के साथ इसे संभाल लेगा?
सारावनबलागी रामचंद्रन

31

यहाँ आदेश के बीच मतभेदों को दिखाने के लिए एक तालिका प्रारूप में एक सिंहावलोकन है Pool.apply, Pool.apply_async, Pool.mapऔर Pool.map_async। एक का चयन करते समय, आपको मल्टी-आर्ग, कंसीडर, ब्लॉकिंग और ऑर्डर को ध्यान में रखना होगा:

                  | Multi-args   Concurrence    Blocking     Ordered-results
---------------------------------------------------------------------
Pool.map          | no           yes            yes          yes
Pool.map_async    | no           yes            no           yes
Pool.apply        | yes          no             yes          no
Pool.apply_async  | yes          yes            no           no
Pool.starmap      | yes          yes            yes          yes
Pool.starmap_async| yes          yes            no           no

टिप्पणियाँ:

  • Pool.imapऔर Pool.imap_async- नक्शा और map_async का lazier संस्करण।

  • Pool.starmap विधि, कई तर्कों की स्वीकृति के अलावा मानचित्र विधि के समान है।

  • Asyncविधियाँ एक बार में सभी प्रक्रियाएँ प्रस्तुत करती हैं और एक बार समाप्त होने के बाद परिणाम निकालती हैं। परिणाम प्राप्त करने के लिए विधि का उपयोग करें।

  • Pool.map(या Pool.apply) विधियाँ बहुत हद तक बिल्ट-इन मैप (या लागू) के समान हैं। वे सभी प्रक्रियाओं को पूरा करने और परिणाम को वापस करने तक मुख्य प्रक्रिया को अवरुद्ध करते हैं।

उदाहरण:

नक्शा

एक समय में नौकरियों की सूची के लिए कहा जाता है

results = pool.map(func, [1, 2, 3])

लागू

केवल एक काम के लिए बुलाया जा सकता है

for x, y in [[1, 1], [2, 2]]:
    results.append(pool.apply(func, (x, y)))

def collect_result(result):
    results.append(result)

map_async

एक समय में नौकरियों की सूची के लिए कहा जाता है

pool.map_async(func, jobs, callback=collect_result)

apply_async

केवल एक नौकरी के लिए बुलाया जा सकता है और समानांतर में पृष्ठभूमि में नौकरी निष्पादित करता है

for x, y in [[1, 1], [2, 2]]:
    pool.apply_async(worker, (x, y), callback=collect_result)

Starmap

एक प्रकार है pool.mapजो कई तर्कों का समर्थन करता है

pool.starmap(func, [(1, 1), (2, 1), (3, 1)])

starmap_async

Starmap () और map_async () का एक संयोजन जो पुनरावृत्तियों के पुनरावृत्तियों पर पुनरावृत्त करता है और इसे पुनरावृत्त किए गए पुनरावृत्तियों के साथ कॉल करता है। परिणाम वस्तु देता है।

pool.starmap_async(calculate_worker, [(1, 1), (2, 1), (3, 1)], callback=collect_result)

संदर्भ:

यहां पूर्ण प्रलेखन ढूंढें: https://docs.python.org/3/library/multiprocessing.html


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