Existe-t-il une classe Pool pour les threads de travail , similaire à la classe Pool du module de multitraitement ?
J'aime par exemple la manière simple de paralléliser une fonction de carte
def long_running_func(p):
c_func_no_gil(p)
p = multiprocessing.Pool(4)
xs = p.map(long_running_func, range(100))
cependant je voudrais le faire sans la surcharge de créer de nouveaux processus.
Je connais le GIL. Cependant, dans mon cas d'utilisation, la fonction sera une fonction C liée aux IO pour laquelle le wrapper python libérera le GIL avant l'appel de la fonction réelle.
Dois-je écrire mon propre pool de threads?
from multiprocessing.pool import ThreadPool
.I know about the GIL. However, in my usecase, the function will be an IO-bound C function for which the python wrapper will release the GIL before the actual function call.
?Réponses:
Je viens de découvrir qu'il existe en fait une interface de pool basée sur les threads dans le
multiprocessing
module, mais elle est quelque peu cachée et n'est pas correctement documentée.Il peut être importé via
Il est implémenté à l'aide d'une classe Process factice enveloppant un thread python. Cette classe de processus basée sur les threads peut être trouvée dans
multiprocessing.dummy
laquelle est brièvement mentionnée dans la documentation . Ce module factice fournit censément l'ensemble de l'interface de multitraitement basée sur les threads.la source
multiprocessing.dummy.Pool
/multiprocessing.pool.ThreadPool
sont la même chose et sont tous deux des pools de threads. Ils imitent l' interface d'un pool de processus, mais ils sont entièrement implémentés en termes de threading. Relisez les documents, vous les avez à l'envers.multiprocessing.dummy
réplique l'API demultiprocessing
mais n'est rien de plus qu'un wrapper autour duthreading
module."multiprocessing
en général, il s'agit de processus, mais pour permettre de basculer entre les processus et les threads, ils ont (principalement) répliqué l'multiprocessing
API dansmultiprocessing.dummy
, mais soutenu par des threads, pas des processus. L'objectif est de vous permettreimport multiprocessing.dummy as multiprocessing
de changer le code basé sur les processus en code basé sur les threads.En Python 3, vous pouvez utiliser
concurrent.futures.ThreadPoolExecutor
, c'est-à-dire:Voir la documentation pour plus d'informations et d'exemples.
la source
sudo pip install futures
ThreadPoolExecutor
etmultiprocessing.dummy.Pool
?Oui, et il semble avoir (plus ou moins) la même API.
la source
ThreadPool
est différent dePool
. L'importation correcte estfrom multiprocessing.pool import ThreadPool
.Pour quelque chose de très simple et léger (légèrement modifié d' ici ):
Pour prendre en charge les rappels à la fin de la tâche, vous pouvez simplement ajouter le rappel au tuple de la tâche.
la source
Queue.get()
est bloquant) jusqu'à la fin du programme, après quoi ils se terminent automatiquement.Queue.join()
va réellement rejoindre la file d'attente des tâches, pas les threads de travail. Ainsi, lorsque la file d'attente est vide,wait_completion
retourne, le programme se termine et les threads sont récoltés par le système d'exploitation.pool.wait_completion()
revient. Le résultat est que les threads continuent de se construire.Salut pour utiliser le pool de threads en Python, vous pouvez utiliser cette bibliothèque:
puis pour utilisation, cette bibliothèque fait comme ça:
Les threads sont le nombre de threads que vous souhaitez et les tâches sont une liste des tâches les plus mappées au service.
la source
.close()
et.join()
appels et que les causes.map()
à la fin avant que tous les fils sont terminés. Juste un avertissement.Voici le résultat que j'ai finalement utilisé. C'est une version modifiée des classes par dgorissen ci-dessus.
Fichier:
threadpool.py
Pour utiliser la piscine
la source
#!/usr/bin/python3
)for i, d in enumerate(delays):
puis ignorez lai
valeur?i
pendant une course.create_task
y a-t-il? Pourquoi est-ce?Les frais généraux liés à la création de nouveaux processus sont minimes, surtout lorsqu'il ne s'agit que de 4 d'entre eux. Je doute que ce soit un point chaud de performance de votre application. Restez simple, optimisez où vous devez et où les résultats du profilage pointent.
la source
Il n'y a pas de pool basé sur les threads. Cependant, il peut être très rapide d'implémenter une file d'attente producteur / consommateur avec la
Queue
classe.De: https://docs.python.org/2/library/queue.html
la source
concurrent.futures
module.from multiprocessing.pool import ThreadPool
une autre façon peut être d'ajouter le processus au pool de files d'attente
la source