मल्टीप्रोसेसिंग: एक प्रगति बार प्रदर्शित करने के लिए tqdm का उपयोग करें


103

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

प्रत्यारोपित समाधान (यानी, रेंज tqdm.tqdm पर सीधे कॉल tqdm (रेंज (0, 30)) मल्टीप्रोसेसिंग के साथ काम नहीं करता है (जैसा कि नीचे दिए गए कोड में तैयार किया गया है)।

प्रगति पट्टी 0 से 100% तक प्रदर्शित होती है (जब अजगर कोड पढ़ता है?) लेकिन यह मानचित्र फ़ंक्शन की वास्तविक प्रगति का संकेत नहीं देता है।

एक प्रगति पट्टी कैसे प्रदर्शित करें जो इंगित करती है कि 'मैप' फ़ंक्शन किस चरण पर है?

from multiprocessing import Pool
import tqdm
import time

def _foo(my_number):
   square = my_number * my_number
   time.sleep(1)
   return square 

if __name__ == '__main__':
   p = Pool(2)
   r = p.map(_foo, tqdm.tqdm(range(0, 30)))
   p.close()
   p.join()

किसी भी मदद या सुझाव का स्वागत करते हैं ...


क्या आप प्रगति बार के कोड स्निपेट को पोस्ट कर सकते हैं?
एलेक्स

2
के साथ एक समाधान के लिए खोज में लोगों के लिए .starmap(): यहाँPool जोड़ने के लिए एक पैच है .istarmap(), जो भी साथ काम करेगा tqdm
Darkonaut

जवाबों:


137

मानचित्र के बजाय इमैप का उपयोग करें, जो संसाधित मूल्यों का एक पुनरावृत्ति देता है।

from multiprocessing import Pool
import tqdm
import time

def _foo(my_number):
   square = my_number * my_number
   time.sleep(1)
   return square 

if __name__ == '__main__':
   with Pool(2) as p:
      r = list(tqdm.tqdm(p.imap(_foo, range(30)), total=30))

14
एक संलग्नक सूची () स्टेटमेंट पुनरावृत्त के समाप्त होने की प्रतीक्षा करता है। कुल = भी आवश्यक है क्योंकि tqdm को यह पता नहीं है कि पुनरावृत्ति कब तक होगी,
hkyi

15
वहाँ के लिए एक समान समाधान है starmap()?
तारापीका

2
for i in tqdm.tqdm(...): pass एक और अधिक सीधे आगे हो सकता है, किlist(tqdm.tqdm)
savfod

1
यह काम करता है, लेकिन क्या किसी और के पास प्रत्येक पुनरावृत्ति के लिए एक प्रगति रेखा पर लगातार प्रगति का प्रिंट था?
डेनिस सुबचेव

3
व्यवहार विशिष्ट होने पर तार दिया जाता chunk_sizeहै p.imaptqdmहर चंक के बजाय हर पुनरावृत्ति को अपडेट कर सकते हैं ?
हुआंगबिबुई

54

समाधान मिला: सावधान! मल्टीप्रोसेसिंग, आकलन समय (प्रति पाश, कुल समय, इत्यादि) के कारण अस्थिर हो सकता है, लेकिन प्रगति पूरी तरह से समाप्त हो जाती है।

नोट: पूल के लिए संदर्भ प्रबंधक केवल पायथन संस्करण 3.3 से उपलब्ध है

from multiprocessing import Pool
import time
from tqdm import *

def _foo(my_number):
   square = my_number * my_number
   time.sleep(1)
   return square 

if __name__ == '__main__':
    with Pool(processes=2) as p:
        max_ = 30
        with tqdm(total=max_) as pbar:
            for i, _ in enumerate(p.imap_unordered(_foo, range(0, max_))):
                pbar.update()

2
pbar.close()आवश्यक नहीं है, यह with
सागर कर

5
क्या यहां दूसरा / आंतरिक tqdmकॉल आवश्यक है?
छायाकार shadow

7
प्रश्न में "r" के रूप में लौटाए जाने वाले _foo (my_number) के उत्पादन के बारे में क्या?
Likak

3
वहाँ के लिए एक समान समाधान है starmap()?
तारापीका

2
@shadowtalker - यह बिना काम करने लगता है;)। वैसे भी - imap_unorderedयहाँ कुंजी है, यह सर्वश्रेष्ठ प्रदर्शन और सर्वोत्तम प्रगति बार अनुमान देता है।
टॉमस गैंडर

21

आप p_tqdmइसके बजाय उपयोग कर सकते हैं ।

https://github.com/swansonk14/p_tqdm

from p_tqdm import p_map
import time

def _foo(my_number):
   square = my_number * my_number
   time.sleep(1)
   return square 

if __name__ == '__main__':
   r = p_map(_foo, list(range(0, 30)))

1
यह बहुत अच्छी तरह से काम करता है, और यह बहुत आसान था pip install। यह मेरी अधिकांश जरूरतों के लिए tqdm की जगह ले रहा है
crypdick

मर्सी विक्टर;)
गेब्रियल रोमन

p_tqdmतक सीमित है multiprocessing.Pool, थ्रेड के लिए उपलब्ध नहीं है
pateheo

19

देर से आने के लिए क्षमा करें, लेकिन यदि आप सभी की जरूरत है एक समवर्ती नक्शा है, नवीनतम संस्करण ( tqdm>=4.42.0) में अब यह अंतर्निहित है:

from tqdm.contrib.concurrent import process_map  # or thread_map
import time

def _foo(my_number):
   square = my_number * my_number
   time.sleep(1)
   return square 

if __name__ == '__main__':
   r = process_map(_foo, range(0, 30), max_workers=2)

संदर्भ: https://tqdm.github.io/docs/contrib.concurrent/ और https://github.com/tqdm/tqdm/blob/master/examples/parallel_bars.py


1
इसके लिए धन्यवाद। आसानी से काम करता है, मैं किसी भी अन्य समाधान की तुलना में बेहतर है।
user3340499

कूल (+1), लेकिन HBox(children=(FloatProgress(value=0.0, max=30.0), HTML(value='')))जुपिटर में फेंकता है
acbe इसहाक


मैं tqdm_notebook हैक करने के लिए चर्चा के साथ एक समस्या देखता हूं, हालांकि, tqdm.contrib.concurrent के समाधान के लिए समाधान नहीं कर सकता।
.बे इसाक

8

Xavi मार्टिनेज के उत्तर के आधार पर मैंने फ़ंक्शन लिखा imap_unordered_bar। यह उसी तरह से उपयोग किया जा सकता है जैसे imap_unorderedकि केवल अंतर के साथ एक प्रसंस्करण बार दिखाया गया है।

from multiprocessing import Pool
import time
from tqdm import *

def imap_unordered_bar(func, args, n_processes = 2):
    p = Pool(n_processes)
    res_list = []
    with tqdm(total = len(args)) as pbar:
        for i, res in tqdm(enumerate(p.imap_unordered(func, args))):
            pbar.update()
            res_list.append(res)
    pbar.close()
    p.close()
    p.join()
    return res_list

def _foo(my_number):
    square = my_number * my_number
    time.sleep(1)
    return square 

if __name__ == '__main__':
    result = imap_unordered_bar(_foo, range(5))

3
यह एक नई लाइन पर प्रत्येक चरण में बार को फिर से तैयार करेगा। उसी लाइन को कैसे अपडेट करें?
misantroop

मेरे मामले में समाधान (Windows / Powershell): Colorama।
misantroop

'pbar.close () की आवश्यकता नहीं है,' के साथ समाप्ति पर यह स्वतः ही बंद हो जाएगा 'जैसी टिप्पणी सागर ने @ scipy के उत्तर पर की है
तेजस शेट्टी

1

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

def par_proc(job_list, num_cpus=None, verbose=False):

# Get the number of cores
if not num_cpus:
    num_cpus = psutil.cpu_count(logical=False)

print('* Parallel processing')
print('* Running on {} cores'.format(num_cpus))

# Set-up the queues for sending and receiving data to/from the workers
tasks_pending = mp.Queue()
tasks_completed = mp.Queue()

# Gather processes and results here
processes = []
results = []

# Count tasks
num_tasks = 0

# Add the tasks to the queue
for job in job_list:
    for task in job['tasks']:
        expanded_job = {}
        num_tasks = num_tasks + 1
        expanded_job.update({'func': pickle.dumps(job['func'])})
        expanded_job.update({'task': task})
        tasks_pending.put(expanded_job)

# Set the number of workers here
num_workers = min(num_cpus, num_tasks)

# We need as many sentinels as there are worker processes so that ALL processes exit when there is no more
# work left to be done.
for c in range(num_workers):
    tasks_pending.put(SENTINEL)

print('* Number of tasks: {}'.format(num_tasks))

# Set-up and start the workers
for c in range(num_workers):
    p = mp.Process(target=do_work, args=(tasks_pending, tasks_completed, verbose))
    p.name = 'worker' + str(c)
    processes.append(p)
    p.start()

# Gather the results
completed_tasks_counter = 0

with tqdm(total=num_tasks) as bar:
    while completed_tasks_counter < num_tasks:
        results.append(tasks_completed.get())
        completed_tasks_counter = completed_tasks_counter + 1
        bar.update(completed_tasks_counter)

for p in processes:
    p.join()

return results

0
import multiprocessing as mp
import tqdm


some_iterable = ...

def some_func():
    # your logic
    ...


if __name__ == '__main__':
    with mp.Pool(mp.cpu_count()-2) as p:
        list(tqdm.tqdm(p.imap(some_func, iterable), total=len(iterable)))

-2

यह सरल है और यह काम करता है।

from multiprocessing.pool import ThreadPool
import time
from tqdm import tqdm

def job():
    time.sleep(1)
    pbar.update()

pool = ThreadPool(5)
with tqdm(total=100) as pbar:
    for i in range(100):
        pool.apply_async(job)
    pool.close()
    pool.join()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.