Python Language Le module de multitraitement


Exemple

from __future__ import print_function
import multiprocessing


def countdown(count):
    while count > 0:
        print("Count value", count)
        count -= 1
    return

if __name__ == "__main__":
    p1 = multiprocessing.Process(target=countdown, args=(10,))
    p1.start()

    p2 = multiprocessing.Process(target=countdown, args=(20,))
    p2.start()

    p1.join()
    p2.join()

Ici, chaque fonction est exécutée dans un nouveau processus. Comme une nouvelle instance de Python VM exécute le code, il n'y a pas de GIL et le parallélisme s'exécute sur plusieurs cœurs.

La méthode Process.start lance ce nouveau processus et exécute la fonction passée dans l'argument target avec les arguments args . La méthode Process.join attend la fin de l'exécution des processus p1 et p2 .

Les nouveaux processus sont lancés différemment selon la version de python et la plateforme sur laquelle le code est exécuté, par exemple :

  • Windows utilise spawn pour créer le nouveau processus.
  • Avec les systèmes unix et la version antérieure à la version 3.3, les processus sont créés à l'aide d'un fork .
    Notez que cette méthode ne respecte pas l'utilisation POSIX de fork et conduit donc à des comportements inattendus, notamment lors de l'interaction avec d'autres bibliothèques multiprocesseurs.
  • Avec le système unix et la version 3.4+, vous pouvez choisir de lancer les nouveaux processus avec fork , forkserver ou spawn utilisant multiprocessing.set_start_method au début de votre programme. forkserver méthodes de forkserver et de spawn sont plus lentes que les méthodes de forking mais évitent certains comportements inattendus.

Utilisation de la fourche POSIX :

Après un fork dans un programme multithread, l'enfant peut en toute sécurité appeler uniquement les fonctions async-signal-safe jusqu'à ce qu'il appelle execve.
( voir )

En utilisant fork, un nouveau processus sera lancé avec exactement le même état pour tous les mutex actuels, mais seul le MainThread sera lancé. Ceci est dangereux car cela pourrait conduire à des conditions de course, par exemple :

  • Si vous utilisez un Lock dans MainThread et le transmettez à un autre thread qui est censé le verrouiller à un moment donné. Si le fork simultanément, le nouveau processus démarrera avec un verrou verrouillé qui ne sera jamais publié car le deuxième thread n'existe pas dans ce nouveau processus.

En fait, ce type de comportement ne devrait pas se produire en python pur, car le multiprocessing gère correctement, mais si vous interagissez avec d'autres bibliothèques, ce type de comportement peut entraîner un blocage de votre système (par exemple, numpy / accéléré sur macOS).