Si chaque processus connaît le nombre de messages à envoyer, les étapes suivantes peuvent être conçues pour résoudre le problème:
1) Réduire le nombre de message à envoyer au processus racine. Chaque processus envoie à la racine le nombre de messages qu'il enverra plus tard. Cette opération est appelée une réduction et elle peut être réalisée par la fonction comm.reduce(...)
2) Recevoir tous les messages sur le processus 0.
Voici un code basé sur la vôtre, qui devrait faire l'affaire. Il peut être couru par mpirun -np 4 python main.py
#passRandomDraw.py
import numpy
from mpi4py import MPI
from mpi4py.MPI import ANY_SOURCE
import numpy as np
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
#just in case, if numpy.random is seed with
np.random.seed(np.random.randint(np.iinfo(np.uint32).min,np.iinfo(np.uint32).max)+rank)
if rank == 0:
randNum = numpy.zeros(1)
print "Process before receiving random numbers"
nb=np.empty((1,),dtype=int)
nb0=np.zeros((1,),dtype=int)
comm.Reduce([nb0, MPI.INT],[nb, MPI.INT],op=MPI.SUM, root=0) #sums the total number of random number from every process on rank 0, in nb.
#print "rank"+str(rank)+" nb "+str(nb)
else:
nb=np.empty((1,),dtype=int)
nb[0]=np.random.randint(1,10)
#print "rank"+str(rank)+" nb "+str(nb)
comm.Reduce([nb, MPI.INT],None,op=MPI.SUM, root=0)
for i in range(0,nb[0],1):
randNum = numpy.zeros(1)
randNum = numpy.random.random_sample(1)
print "Process", rank, "iteration", i, "drew the number", randNum[0]
comm.Send(randNum, dest=0)
if rank == 0:
for i in range(nb[0]): #receives nb message, each one with its int.
comm.Recv(randNum, ANY_SOURCE)
print "Process", rank, "received the number", randNum[0]
Selon le documentation of numpy.random()
le générateur de nombres pseudo-aléatoires Mersenne Twister est initialement ensemencé par un nombre extrait de /dev/urandom
(ou l'analogue Windows) si elle est disponible ou de graines de l'horloge autrement. Ainsi, dans le dernier cas, tous les processus peuvent recevoir la même graine et générer les mêmes nombres aléatoires. Pour éviter cela, j'ai ajouté la ligne suivante:
np.random.seed(np.random.randint(np.iinfo(np.uint32).min,np.iinfo(np.uint32).max)+rank)
Juste pour clarifier/confirmer. Ai-je raison de supposer que vous n'avez aucune chance de savoir d'avance combien de messages chaque rang enverra, même sur le rang lui-même? – Zulan
Idéalement, je voudrais envoyer des messages de chaque rang sans avoir à connaître le nombre de messages que le rang enverra. Si ce n'est pas possible, il serait possible de calculer dans le rang combien de messages seront envoyés, mais cela serait différent pour chaque rang. – 218