Je pensais que je simplifierais les exemples les plus simples copiés ci-dessus, en travaillant pour moi sur Py3.6. Le plus simple est multiprocessing.Pool
:
import multiprocessing
import time
def worker(x):
time.sleep(1)
return x
pool = multiprocessing.Pool()
print(pool.map(worker, range(10)))
Vous pouvez définir le nombre de processus dans la piscine avec, par exemple, Pool(processes=5)
. Cependant, la valeur par défaut est le nombre de processeurs, alors laissez ce champ vide pour les tâches liées au processeur. (Les tâches liées aux E / S conviennent souvent aux threads de toute façon, car les threads attendent la plupart du temps et peuvent partager un cœur de processeur.) AppliquePool
également l' optimisation de la segmentation .
(Notez que la méthode de travail ne peut pas être imbriquée dans une méthode. J'ai initialement défini ma méthode de travail à l'intérieur de la méthode qui fait l'appel pool.map
, pour qu'elle reste entièrement autonome, mais les processus n'ont pas pu l'importer et j'ai jeté "AttributeError : Impossible de sélectionner l'objet local external_method..inner_method ". Plus d'informations ici . Cela peut être à l'intérieur d'une classe.)
(J'apprécie l'impression de la question d'origine 'represent!'
plutôt que time.sleep()
, mais sans elle, je pensais que du code s'exécutait simultanément alors qu'il ne l'était pas.)
Py3 ProcessPoolExecutor
est également composé de deux lignes ( .map
renvoie un générateur donc vous avez besoin du list()
):
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
print(list(executor.map(worker, range(10))))
Avec plaine Process
:
import multiprocessing
import time
def worker(x, queue):
time.sleep(1)
queue.put(x)
queue = multiprocessing.SimpleQueue()
tasks = range(10)
for task in tasks:
multiprocessing.Process(target=worker, args=(task, queue,)).start()
for _ in tasks:
print(queue.get())
À utiliser SimpleQueue
si tout ce dont vous avez besoin est put
et get
. La première boucle démarre tous les processus, avant que la seconde effectue les queue.get
appels de blocage . Je ne pense pas qu'il y ait de raison d'appeler p.join()
aussi.
multiprocessing.Queue
, plutôt qu'unManager
ici. L'utilisation de aManager
nécessite de créer un processus entièrement nouveau, ce qui est excessif quand unQueue
ferait l'affaire.