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 ProcessPoolExecutorest également composé de deux lignes ( .maprenvoie 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 SimpleQueuesi tout ce dont vous avez besoin est putet get. La première boucle démarre tous les processus, avant que la seconde effectue les queue.getappels de blocage . Je ne pense pas qu'il y ait de raison d'appeler p.join()aussi.
multiprocessing.Queue, plutôt qu'unManagerici. L'utilisation de aManagernécessite de créer un processus entièrement nouveau, ce qui est excessif quand unQueueferait l'affaire.