MPI标准3.0,关于mpi_scatterv:
计数,类型和位移的规范不应导致根目录上的任何位置被多次读取。"
但是,我使用下面的代码在python中测试mpi4py并不表示从root用户读取数据有多次出现问题:
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
命令
> mpirun -np 7 python mycode.py
产生
[ 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.]
输出显然是正确的,并且来自根(过程0)的数据在每个边界点处被明确地引用了不止一次。我不理解MPI标准吗?或者这是一种一般不能依赖的偶然行为?
FWIW,我在OSX上运行python 2.7。
答案 0 :(得分:2)
你不能依赖这个。
这个假设直接源于MPI标准。由于mpi4py大写函数只是MPI之上的一个薄层,这才是最重要的。该标准还指出:
基本原理。虽然不需要,但最后的限制是强制执行的 用
MPI_GATHER
实现对称,其中有相应的限制 (多写限制)是必要的。 (理由结束。)
考虑到它在标准中,MPI实现可以使用它:
最后一点是最可怕的,因为它可能会引入微妙的错误。考虑到发送缓冲区的只读性质,很难想象这样的优化,但这并不意味着它确实存在/不存在。正如一个想法考虑strict aliasing optimizations。另请注意,MPI实现非常复杂 - 它们的行为可能会在版本,配置,数据大小或其他环境变化之间变得看似不稳定。
还有一个臭名昭着的例子memcpy
:标准禁止重叠内存输入,并且在某些时候,glibc实现利用它来进行微小的争议优化。不满足要求的代码开始失败,用户开始听到strange sound on mp3 flash websites,然后是heated debate涉及Linus Torvalds和Ulrich Drepper。
故事的士气是:遵循标准规定的要求,即使它现在有效,但要求对你没有意义。也很高兴有这么详细的标准。
答案 1 :(得分:2)
MPI标准包括许多要求,这些要求通常不会被实施严格检查,主要是出于性能原因。理由是,根据标准,任何正确的程序在给定一组宽松约束的情况下也是正确的。依赖于这种特定于实现的行为会导致不可移植的代码,并且违反标准。
有许多正当理由要求不相交的发送段。立即可见的是MPI_Gatherv
的对称性。对于后者,段必须是不相交的,否则收集后的内存内容将取决于底层接收操作的顺序。由于在典型的MPI程序中,散布通常由道集镜像,因此如果相同的约束同时适用于聚集和散布,则可以重用计算的偏移和计数阵列。一个不太明显的原因是,在某些体系结构中,网络设备可能不允许从重叠的内存区域同时读取。
由于非标准MPI行为很容易在开发过程中蔓延到程序代码中,因此可能需要使用像MUST这样的工具来检查程序的正确性。