0

Je suis un programmeur parallèle expert dans OpenMP et C++. Maintenant, j'essaie de comprendre le parallélisme en python et la bibliothèque multiprocessing.Comment implémenter une opération de réduction dans le multitraitement python?

En particulier, je suis en train de paralléliser ce code simple, qui incrémente un tableau au hasard 100 fois:

from random import randint 
import multiprocessing as mp 
import numpy as np 

def random_add(x): 
    x[randint(0,len(x)-1)] += 1 

if __name__ == "__main__": 
    print("Serial") 
    x = np.zeros(8) 
    for i in range(100): 
     random_add(x) 
    print(x) 

    print("Parallel") 
    x = np.zeros(8)  
    processes = [mp.Process(target = random_add, args=(x,)) for i in range(100)] 
    for p in processes: 
     p.start() 
    print(x) 

Cependant, la sortie est la suivante:

Serial 
[ 9. 18. 11. 15. 16. 8. 10. 13.] 
Parallel 
[ 0. 0. 0. 0. 0. 0. 0. 0.] 

Pourquoi arrive? Eh bien, je pense avoir une explication: puisque nous sommes en multitraitement (et non multi-threading), chaque processus est sa propre section de mémoire, c'est-à-dire que chaque processus engendré a son propre x, qui est détruit une fois que random_add(x) est terminé. En conclusion, le x dans le programme principal n'est jamais vraiment mis à jour.

Est-ce correct? Et si oui, comment puis-je résoudre ce problème? En quelques mots, j'ai besoin d'une opération globale de réduction qui somme les résultats de tous les appels random_add, obtenant le même résultat de la version sérielle.

+1

Vous avez raison dans votre diagnostic. Voir [certaines solutions de contournement] (https://docs.python.org/3.6/library/multiprocessing.html#sharing-state-between-processes) dans la bibliothèque multitraitement. –

+0

sous-processus obtenir une copie de votre variable 'x' mais pas l'original. C'est donc une question commune sur le partage de variables en multitraitement. Il suffit de le rechercher car il y a un looooot d'information existé. – Sraw

+0

Merci pour les deux commentaires. Cela signifie également que si x est potentiellement gros, le code va prendre une éternité? Juste pour comprendre le processus :) – justHelloWorld

Répondre

1

Vous devez utiliser des objets de mémoire partagée dans votre cas:

from random import randint 
import multiprocessing as mp 

def random_add(x): 
    x[randint(0,len(x)-1)] += 1 

if __name__ == "__main__": 
    print("Serial") 
    x = [0]*8 
    for i in range(100): 
     random_add(x) 
    print(x) 

    print("Parallel") 
    x = mp.Array('i', range(8)) 
    processes = [mp.Process(target = random_add, args=(x,)) for i in range(100)] 
    for p in processes: 
     p.start() 
    print(x[:]) 

J'ai changé tableau numpy à la liste ordinale dans le but de clarté code

+0

Merci pour votre réponse. Que faire si j'ai un 'Array()' de tableaux numpy? Donc 'x [randint (0, len (x) -1]' est en fait un 'numpy.array' Je pense que ce sera sûr, mais une seconde opinion est toujours utile: D – justHelloWorld

+1

Lisez [cette réponse] (https : //stackoverflow.com/questions/7894791/use-numpy-array-in-shared-memory-for-multiprocessing) à propos des tableaux numériques et de la mémoire partagée –