2016-04-12 7 views
2

Je ne trouve pas de question simmilar ici, alors voici Pourquoi le code suivant affiche-t-il toujours (False, None)? Ne devrait-il pas être (True, None), si le test() a été appelé 3 secondes après le processus 0 envoyer le message? Aussi, si j'appelle req.wait() avant le test() j'obtiens la sortie dont j'ai besoin, mais alors ce n'est pas non-bloquable, donc test() perd son but (je veux pouvoir dire que le processus 1 a reçu un message de n'importe quelle source pendant ces 3 secondes il dormait)Mpi4py mpi_test retourne toujours faux

code:

import time 
from mpi4py import MPI 

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

if rank == 0: 
    req = comm.isend(0, 1, tag=0); 
    req.wait(); 
elif rank == 1: 
    req = comm.irecv(); 
    time.sleep(3); 
    print req.test(); 
+0

Etes-vous sûr que c'est le programme que vous utilisez? Il y a des ';' qui n'appartiennent pas. Que se passe-t-il si vous mettez 'sleep/test' dans une boucle? – Zulan

+0

Bizarre. Si j'appelle la commande 'test' deux fois de suite, la deuxième (et toute ultérieure) est bonne. Pourtant, pas un comportement normal, donc si quelqu'un peut me donner d'autres instructions, il serait apprécié .. –

Répondre

1

Je ne suis pas expert en mpi4py, mais en supposant qu'il se comporte comme son homologue MPI C (ce qui semble être une hypothèse juste), alors en effet, il y a peu de surprise ici.

Eh bien, en toute justice, la sortie de votre code n'est pas indiquée par la norme MPI. Qu'est-ce que les garanties est que, après un nombre des appels à la fonction MPI_Test(), il renverra true. Ce nombre peut être n'importe quoi, et donc il renvoie true au premier appel, ou à la seconde, ou seulement après un milliard d'appels ... Par conséquent, la manière habituelle/recommandée d'utiliser la fonction MPI_Test() est de l'utiliser ici et là, et de terminer avec soit une boucle infinie (avec une condition de sortie basée sur sa sortie), soit utiliser un appel MPI_Wait(). Maintenant, la raison en est la suivante: la bibliothèque MPI n'effectue généralement aucune action en dehors des appels MPI explicites. Par conséquent, afin de voir une communication non bloquante à progresser, vous devez effectuer certains appels MPI. Ces appels n'ont pas besoin d'être liés aux communications permanentes (généralement tout appel MPI déclenchera en interne un certain niveau de progression de la file d'attente des messages) mais vous devez donner la main à la bibliothèque MPI pour l'obtenir. Et c'est ce que font les appels à MPI_Test(). Et cela explique aussi pourquoi ce n'est pas vraiment lié au temps: votre appel à la fonction sleep() donne en effet le temps à la communication de se produire, mais comme la bibliothèque MPI ne reçoit pas la main, rien ne s'est réellement passé.

Enfin, une certaine modération à mes explications ci-dessus:

  1. Les ci-dessus suppose pas mécanisme externe pour faire avancer les messages en vol. Cependant, les moteurs d'accès direct à la mémoire (à distance), tels que ceux disponibles sur les cartes InfiniBand par exemple, peuvent en effet faire progresser les messages sans avoir à effectuer d'appels MPI supplémentaires. Cependant, cela ne se produit généralement que pour les communications entre nœuds et dépend fortement de votre matériel et de vos logiciels.
  2. Certaines bibliothèques MPI offrent comme extension la possibilité de dédier un thread CPU pour faire progresser la communication MPI en dehors des appels MPI. Certaines bibliothèques MPI basées sur MPICH, comme Intel MPI par exemple, proposent la variable d'environnement MPICH_ASYNC_PROGRESS qui, une fois définie sur 1, déclenchera la création de ce thread de communication MPI pour faire progresser les communications non bloquantes derrière la scène. Je ne sais pas si OpenMPI propose cette fonctionnalité aussi ...
0

Peut-être que c'est juste parce que vous avez créé cet exemple en éditant un programme plus grand, mais je voulais juste vérifier qu'ils ne sont pas un malentendu sous-jacent des communications MPI non bloquantes ...

Je ne comprends pas pourquoi vous avez:

req = comm.isend(0, 1, tag=0); 
req.wait(); 

puisque c'est fonctionnellement identique à l'appel de blocage

comm.send(0, 1, tag=0); 

Bien sûr, la forme non-blocage signifie que vous pouvez ensuite insérer plus code entre isend et attendez ce qui est peut-être ce que vous voulez faire.

+0

C'est, plus ou moins, c'est un test, puisque je suis nouveau à MPI, le code que j'ai montré dans mon post fonctionne comme je l'ai décrit et il est isolé dans son propre script. –