2016-04-12 5 views
2

La norme MPI, 3.0, dIt mpi_scatterv:MPI, python, Scatterv, et les données qui se chevauchent

La spécification des comptages, les types et les déplacements ne devrait causer aucun emplacement sur la racine à lire plus une fois «

Cependant, mes tests de mpi4py en python avec le code ci-dessous ne signifie pas qu'il ya un problème avec les données de lecture de la racine plus d'une fois.

import numpy as np 
from sharethewealth import sharethewealth 

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

counts = [16, 17, 16, 16, 16, 16, 15] 
displs = [0, 14, 29, 43, 57, 71, 85] 

if rank == 0: 
    bigx = np.arange(100, dtype=np.float64) 
else: 
    bigx = None 

my_size = counts[rank] 
x = np.zeros(my_size) 

comm.Scatterv([bigx, counts, displs, MPI.DOUBLE], x, root = 0) 

print x 

Commande

> mpirun -np 7 python mycode.py 

produit

[ 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72.] 

[ 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99.] 

[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.] 

[ 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44.] 

[ 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58.] 

[ 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86.] 

[ 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30.] 

La sortie est clairement correcte et les données de la racine (processus 0) a clairement été fait référence plus d'une fois à chacun des points limites. Est-ce que je ne comprends pas la norme MPI? Ou est-ce un comportement fortuit qui ne peut pas être invoqué en général? FWIW, je cours python 2.7 sur OSX.

Répondre

2

Vous ne pouvez pas compter sur cela.

Cette hypothèse découle directement de la norme MPI. Puisque les fonctions majuscules de mpi4py ne sont qu'une couche mince au-dessus de MPI, c'est ce qui compte. La norme stipule également:

Justification. Bien que cela ne soit pas nécessaire, la dernière restriction est imposée afin de parvenir à la symétrie avec MPI_GATHER, où la restriction correspondante (restriction d'écriture multiple) est nécessaire. (Fin de la raison d'être.)

Considérant qu'il est dans la norme, une implémentation MPI peut faire usage de ce qui suit:

  • Ignore violations
  • un avertissement en cas de violation
  • Fail en cas de violation
  • Utilisez ces hypothèses pour tout type d'optimisation pouvant entraîner un comportement indéfini en cas de violation

Le dernier point est le plus effrayant car il peut introduire des bugs subtils. Compte tenu de la nature en lecture seule du tampon d'envoi, il est difficile d'imaginer une telle optimisation, mais cela ne signifie pas qu'elle existe/n'existera pas. Juste comme une idée envisager strict aliasing optimizations. Notez également que les implémentations MPI sont très complexes - leur comportement peut changer de façon apparemment erratique entre les versions, les configurations, les tailles de données ou d'autres changements environnementaux.

Il existe également un exemple infâme avec memcpy: La norme interdit les entrées de mémoire qui se chevauchent, et à un moment donné, l'implémentation de la glibc en a fait usage pour une minuscule optimisation contestée. Le code qui n'a pas satisfait à l'exigence a commencé à échouer, et les utilisateurs ont commencé à entendre strange sound on mp3 flash websites, suivi d'un heated debate impliquant Linus Torvalds et Ulrich Drepper.

Le moral de l'histoire est: Suivez les exigences imposées par la norme, même si cela fonctionne maintenant et l'exigence n'a pas de sens pour vous. Sois également content qu'il y ait une telle norme détaillée.

2

La norme MPI comprend de nombreuses exigences qui ne sont souvent pas strictement vérifiées par les implémentations, principalement pour des raisons de performances. Le raisonnement est que tout programme qui est correct selon la norme sera également correct compte tenu d'un ensemble de contraintes relâchées. S'appuyer sur un tel comportement spécifique à l'implémentation entraîne un code non portable et va à l'encontre de la norme.

Il existe de nombreuses raisons valables d'exiger des segments d'envoi disjoints. Le visible immédiatement est la symétrie avec MPI_Gatherv. Pour ce dernier, les segments doivent être disjoints, sinon le contenu de la mémoire après la collecte dépendra de l'ordre des opérations de réception sous-jacentes. Étant donné que dans un programme MPI typique, les dispersions sont généralement reflétées par des regroupements, les tableaux calculés de décalage et de comptage peuvent être réutilisés si les mêmes contraintes s'appliquent à la collecte et à la dispersion. Une raison moins évidente est que sur certaines architectures, l'équipement de réseau peut ne pas autoriser des lectures simultanées à partir de régions de mémoire se chevauchant.

Comme il est très facile pour le comportement MPI non standard pour se glisser dans le code du programme au cours du développement, on pourrait vouloir utiliser des outils comme notre MUST pour vérifier l'exactitude du programme.

+0

Merci pour cet aperçu. –