web-dev-qa-db-fra.com

Python pool multiprocesseur, rejoindre; n'attendez pas pour continuer?

(1) J'essaie d'utiliser pool.map Suivi de pool.join(), mais python ne semble pas attendre pool.map pour terminer avant de passer la pool.join(). Voici un exemple simple de ce que j'ai essayé:

from multiprocessing import Pool

foo = {1: []}

def f(x):
    foo[1].append(x)
    print foo

def main():
    pool = Pool()
    pool.map(f, range(100))
    pool.close()
    pool.join()
    print foo

if __name__ == '__main__':
    main()

La sortie imprimée est juste {1: []}, Comme si python a simplement ignoré la commande join et a exécuté print foo Avant d'avoir pu exécuter f. Le résultat escompté est que foo est {1:[0,1,...,99]}, et en utilisant le standard intégré python map donne ceci Pourquoi la version regroupée imprime-t-elle {1: []}, et comment puis-je changer mon code pour lui faire imprimer le résultat souhaité?

(2) Idéalement, je voudrais également définir foo comme une variable locale dans main() et la transmettre à f, mais en faisant cela en faisant foo le premier argument de f et en utilisant

pool.map(functools.partial(f, foo), range(100))

produit la même sortie. (et peut-être aussi le problème que chaque processus a maintenant sa propre copie de foo?). Encore une fois, il fonctionne à la place avec le map normal.

17
panavia

Ce n'est pas la bonne façon d'utiliser map.

  1. Utiliser une variable globale de cette façon est absolument faux. Les processus ne partagent pas la même mémoire (normalement), donc chaque f aura sa propre copie de foo. Pour partager une variable entre différents processus, vous devez utiliser un Manager
  2. Les fonctions passées à map sont généralement censées renvoyer une valeur.

Je vous suggère de lire quelques documentation .

Cependant, voici un exemple factice de la façon dont vous pouvez l'implémenter:

from multiprocessing import Pool

foo = {1: []}

def f(x):
    return x

def main():
    pool = Pool()
    foo[1] = pool.map(f, range(100))
    pool.close()
    pool.join()
    print foo

if __name__ == '__main__':
    main()

Vous pouvez également faire quelque chose comme pool.map(functools.partial(f, foo), range(100))foo est un Manager.

25
smeso