web-dev-qa-db-fra.com

Multitraitement: utilisez tqdm pour afficher une barre de progression

Pour rendre mon code plus "pythonique" et plus rapide, j'utilise le "multitraitement" et une fonction de carte pour l'envoyer a) la fonction et b) la plage d'itérations.

La solution implantée (c'est-à-dire, appelez tqdm directement sur la plage tqdm.tqdm (plage (0, 30)) ne fonctionne pas avec le multitraitement (tel que formulé dans le code ci-dessous).

La barre de progression s'affiche de 0 à 100% (lorsque python lit le code?), Mais elle n'indique pas la progression réelle de la fonction de carte.

Comment afficher une barre de progression indiquant à quelle étape se trouve la fonction 'map'?

from multiprocessing import Pool
import tqdm
import time

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

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

Toute aide ou suggestion est la bienvenue ...

59
SciPy

Solution trouvée: soyez prudent! En raison du multitraitement, le temps d'estimation (itération par boucle, temps total, etc.) peut être instable, mais la barre de progression fonctionne parfaitement.

Remarque: Le gestionnaire de contexte pour le pool est uniquement disponible à partir de Python version 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 __== '__main__':
    with Pool(processes=2) as p:
        max_ = 30
        with tqdm(total=max_) as pbar:
            for i, _ in tqdm(enumerate(p.imap_unordered(_foo, range(0, max_)))):
                pbar.update()
36
SciPy

Utilisez imap au lieu de map, qui renvoie un itérateur de valeurs traitées.

from multiprocessing import Pool
import tqdm
import time

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

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

sur la base de la réponse de Xavi Martínez, j’ai écrit la fonction imap_unordered_bar. Il peut être utilisé de la même manière que imap_unordered à la seule différence qu'une barre de traitement est affichée.

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 __== '__main__':
    result = imap_unordered_bar(_foo, range(5))
6
Oliver Wilken

Vous pouvez utiliser p_tqdm à la place.

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 __== '__main__':
   r = p_map(_foo, list(range(0, 30)))
2
Victor Quach

Cette approche simple et ça marche.

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()
0
Vijayabhaskar J