2
votes

Multitraitement Python: vous n'utilisez pas d'espace mémoire séparé?

À ma connaissance, le multiprocessing utilise fork sous Linux, ce qui signifie que chaque processus créé par multiprocessing a son propre espace mémoire et toutes les modifications apportées à l'intérieur n'affectent pas les autres processus fork ed.

Mais j'ai rencontré cette situation plutôt étrange:

-1 -1 -1 -1 -1 4 -1 5 -1 6 -1 8 -1 -1 14 -1 -1 12 -1 -1 -1

Je pensais que ce programme imprimerait exactement 21 -1 , car le multiprocessing crée 20 sous-processus distincts dont les espaces mémoire ne sont pas partagés, ce qui signifie que la ligne i = j n'affectera pas la valeur de i dans tout autre processus; d'où i = -1 au moment de l'impression.

Cependant, le programme a en fait imprimé un mélange de -1 et une quantité aléatoire de nombres entre 0 et 19.

Exemple:

import multiprocessing

i = -1

def change(j):
    global i
    print(i, end=" ")  # should print -1
    i = j 

with multiprocessing.Pool(20) as p:
    p.map(change, range(20))

print(i)  # should print -1

Ma question est donc: pourquoi n'ai-je pas obtenu exactement 21 -1 code> ?


1 commentaires

Bien que vous utilisiez Pool (20) , il ne créera pas vraiment 20 processus tant que cela ne sera pas nécessaire. Ce qui signifie que certaines tâches peuvent être exécutées dans le même processus. Vous pouvez imprimer os.getpid () pour avoir un chèque.


3 Réponses :


1
votes

Multiprocessing.Pool ne garantit pas que chaque tâche sera exécutée dans un nouveau processus. En fait, la raison pour laquelle vous utilisez le multiprocessing.Pool est pour les tâches où le coût de création d'un nouveau processus est considéré comme coûteux, vous voulez donc utiliser un pool de processus pour éviter cette surcharge de création de processus. Le modèle d'utilisation typique pour le multitraitement.Pool est que vous créez beaucoup de tâches, puis créez un pool avec un petit nombre de travailleurs (généralement en fonction du nombre de cœurs de processeur de votre machine), le pool planifiera les tâches pour les travailleurs et réutiliser les processus lorsque cela est possible. Si vous voulez toujours démarrer un nouveau processus, vous devez avoir utilisé le multiprocessing.Process.


0 commentaires


1
votes

Il est courant de croire que ce ne sera pas le cas, mais Pool (20) créera 20 processus immédiatement . En fait, les processus seront tous démarrés avant même que le thread du gestionnaire ne démarre, ce qui alimentera les tâches dans la enquête pour être traitées par les travailleurs plus tard.

Les processus exécutent multiprocessing.pool.worker -code jusqu'à ce qu'ils arrivent à .get () à partir de la enquête . C'est juste que tous ne seront pas reprogrammés pour obtenir des tâches de la file d'attente partagée pendant le peu de temps dont tout cela a besoin. Les lectures de file d'attente sont séquentielles, un seul processus peut en lire à la fois. Certains processus auront plusieurs tâches alors que d'autres ne seront pas planifiés car votre système d'exploitation exécute quelque chose de différent sur les cœurs. C'est lorsqu'un processus reçoit plus d'une tâche ici lorsque vous voyez d'autres valeurs que -1 .


0 commentaires