web-dev-qa-db-fra.com

Quelle est la différence entre ThreadPool et Pool dans le module de multitraitement Python

Quelle est la différence entre ThreadPool et Pool dans le module multiprocessing. Quand j'essaye mon code, c'est la différence principale que je vois:

from multiprocessing import Pool
import os, time

print("hi outside of main()")

def hello(x):
    print("inside hello()")
    print("Proccess id: ", os.getpid())
    time.sleep(3)
    return x*x

if __== "__main__":
    p = Pool(5)
    pool_output = p.map(hello, range(3))

    print(pool_output)

Je vois la sortie suivante:

hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
hi outside of main()
inside hello()
Proccess id:  13268
inside hello()
Proccess id:  11104
inside hello()
Proccess id:  13064
[0, 1, 4]

Avec "ThreadPool":

from multiprocessing.pool import ThreadPool
import os, time

print("hi outside of main()")

def hello(x):
    print("inside hello()")
    print("Proccess id: ", os.getpid())
    time.sleep(3)
    return x*x

if __== "__main__":
    p = ThreadPool(5)
    pool_output = p.map(hello, range(3))

    print(pool_output)

Je vois la sortie suivante:

hi outside of main()
inside hello()
inside hello()
Proccess id:  15204
Proccess id:  15204
inside hello()
Proccess id:  15204
[0, 1, 4]

Mes questions sont:

  • pourquoi le “outside __main __ ()” est-il exécuté chaque fois dans le Pool?

  • multiprocessing.pool.ThreadPool ne génère pas de nouveaux processus? Cela crée juste de nouveaux threads?

  • Si tel est le cas, quelle est la différence entre multiprocessing.pool.ThreadPool et un module threading?

Je ne vois nulle part la documentation officielle de ThreadPool, est-ce que quelqu'un peut m'aider à le trouver?

49
ozn

Le _multiprocessing.pool.ThreadPool_ se comporte comme le _multiprocessing.Pool_ avec la seule différence qui utilise des threads au lieu de processus pour exécuter la logique de travail.

La raison pour laquelle vous voyez

_hi outside of main()
_

être imprimé plusieurs fois avec le _multiprocessing.Pool_ est dû au fait que le pool va engendrer 5 processus indépendants. Chaque processus initialise son propre interpréteur Python et charge le module, ce qui a pour effet d'exécuter à nouveau le niveau supérieur print.

Notez que cela se produit uniquement si la méthode de création de processus spawn est utilisée (méthode disponible uniquement sous Windows). Si vous utilisez la version fork (Unix), le message n’est imprimé qu’une fois de la même manière que pour les threads.

Le _multiprocessing.pool.ThreadPool_ n'est pas documenté car sa mise en œuvre n'a jamais été complétée. Il manque des tests et de la documentation. Vous pouvez voir son implémentation dans le code source .

Je crois que la prochaine question naturelle est la suivante: quand utiliser un pool basé sur des threads et quand utiliser un pool basé sur un processus?

La règle de base est la suivante:

  • Travaux liés aux entrées/sorties -> _multiprocessing.pool.ThreadPool_
  • Travaux liés à la CPU -> _multiprocessing.Pool_
  • Travaux hybrides -> dépend de la charge de travail, je préfère généralement le _multiprocessing.Pool_ en raison de l'avantage que procure l'isolation des processus

Sur Python 3, vous voudrez peut-être jeter un coup d'œil à la mise en œuvre du pool concurrent.future.Executor .

63
noxdafox