2017-03-24 2 views
1

Je suis nouveau sur MPI et mpi4py. J'ai deux problèmes avec le code suivant. Pour un, les données sur le rang 0 ne s'impriment pas, alors que les données de type None sur les autres rangs le font. Deuxièmement, j'obtiens une erreur KeyError '0' de la part de la fonction comm.Scatter(), que je ne peux pas expliquer.comm.Scatter KeyError avec mpi4py

comm = MPI.COMM_WORLD 
size = comm.Get_size() 
rank = comm.Get_rank() 

if rank == 0: 
    df = pickle.load(open('lipad0406.p', 'rb')) 
else: 
    df = None 

p = size 

d = np.array(df) 

n = d.size 

m = n/p 

d_loc = np.zeros(m) 

comm.Scatter(d,d_loc) 

print "process", rank, "x:", d 
print "process", rank, "x_local:", d_loc.size 

Répondre

1

Bien que je ne peux pas reproduire votre erreur particulière, le problème est ici que sur la non-racine rangs d est une erreur avec un seul élément None, d'où n=1 et m sera faux. Si vous ne connaissez pas la taille sur les rangs non root, vous devez d'abord diffuser:

if rank == 0: 
    df = pickle.load(open('lipad0406.p', 'rb')) 
    d = np.array(df, dtype=float) 
    m = d.size/size 
    comm.bcast(m) 
else: 
    d = None 
    m = comm.bcast(None) 

d_loc = np.zeros(m, dtype=float) 

comm.Scatter(d,d_loc) 

Assurez-vous également que le match des types de données.

0

Le KeyError est en cours car Scatter ne peut pas gérer tout type de données en cours de chargement à partir de votre fichier d'entrée. Mpi4py fournit deux types de fonctions de communication, dont les noms commencent par une lettre majuscule, par ex. Scatter, et ceux dont le nom commence par une lettre minuscule, par ex. scatter. méthodes d'instances de Comm fournissent un soutien pour les communications collectives des tampons de mémoire From the Mpi4py documentation:

En MPI pour python, le Bcast(), Scatter(), Rassembler(), Allgather() et Alltoall(). Les variantes bcast(), scatter(), gather(), allgather() et alltoall() peuvent communiquer des objets Python génériques.

Ce qui ne ressort pas de ceci est que même si les tableaux numpy exposent soi-disant des tampons de mémoire, les tampons doivent apparemment être à l'un d'un petit ensemble de types de données primitifs, et certainement ne fonctionnent pas avec des objets génériques. Comparez les deux morceaux de code suivants:

from mpi4py import MPI 
import numpy 

Comm = MPI.COMM_WORLD 
Size = Comm.Get_size() 
Rank = Comm.Get_rank() 

if Rank == 0: 
    Data = numpy.empty(Size, dtype=object) 
else: 
    Data = None 

Data = Comm.scatter(Data, 0) # I work fine! 

print("Data on rank %d: " % Rank, Data) 

et

from mpi4py import MPI 
import numpy 

Comm = MPI.COMM_WORLD 
Size = Comm.Get_size() 
Rank = Comm.Get_rank() 

if Rank == 0: 
    Data = numpy.empty(Size, dtype=object) 
else: 
    Data = None 

Datb = numpy.empty(1, dtype=object) 

Comm.Scatter(Data, Datb, 0) # I throw KeyError! 

print("Datb on rank %d: " % Rank, Datb) 

Vous devriez juste pouvoir utiliser scatter dans votre code sans modification supplémentaire:

d_loc = comm.scatter(d) 

ou éliminer d_loc entièrement , puisque scatter n'a pas besoin d'un tampon de réception distinct comme Scatter fait, et il suffit d'utiliser

d = comm.scatter(d) 

De plus, comme Zulan a dit, vous devez vous assurer que les dtype s de vos tableaux de numpy d et d_loc correspondance et que m est diffusée aux non-rang 0 processus.

Exécution de votre code exactement sauf df = pickle.load(open('lipad0406.p', 'rb')) remplacé par df = range(size), puisque je n'ai pas et ne peut pas beaucoup conjectures sur le contenu de votre dossier, ne manque pas d'imprimer d dans le processus de rang 0, donc je ne peux conjecture que ce problème particulier a quelque chose à voir avec le chargement du fichier.

La version modifiée de travail minimale de votre code, le chargement de fichiers exceptés, est

from mpi4py import MPI 
import numpy as np 

comm = MPI.COMM_WORLD 
size = comm.Get_size() 
rank = comm.Get_rank() 

if rank == 0: 
    df = range(size) 
else: 
    df = None 

p = size 

d = np.array(df) 

n = d.size 

m = comm.bcast(n/p) 

d_loc = np.zeros(m) 

d_loc = comm.scatter(d) 

print "process", rank, "x:", d 
print "process", rank, "x_local:", d_loc.size