MPI、python、Scatterv 和重叠数据

MPI, python, Scatterv, and overlapping data

MPI 标准 3.0 说 mpi_scatterv:

The specification of counts, types, and displacements should not cause any location on the root to be read more than once."

然而,我在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,我 运行 python 2.7 OSX。

你不能依赖这个。

这个假设直接源于 MPI 标准。由于 mpi4py 大写函数只是 MPI 之上的一个薄层,这才是最重要的。该标准还规定:

Rationale. Though not needed, the last restriction is imposed so as to achieve symmetry with MPI_GATHER, where the corresponding restriction (a multiple-write restriction) is necessary. (End of rationale.)

考虑到它在标准中,MPI 实现可能会利用它:

  • 忽略违规行为
  • 违规时发出警告
  • 违反时失败
  • 将此假设用于在违反时可能导致未定义行为的任​​何类型的优化

最后一点最可怕,因为它可能会引入细微的错误。考虑到发送缓冲区的只读性质,很难想象这样的优化,但这并不意味着它 does/will 不存在。作为一个想法考虑 strict aliasing optimizations。另请注意,MPI 实现非常复杂 - 它们的行为可能会在版本、配置、数据大小或其他环境变化之间看似不稳定地变化。

还有一个臭名昭著的例子 memcpy:标准禁止重叠内存输入,在某些时候,glibc 实现利用它进行了一个有争议的小优化。不满足要求的代码开始失败,用户开始听到 strange sound on mp3 flash websites, followed by a heated debate 涉及 Linus Torvalds 和 Ulrich Drepper。

故事的主旨是:遵循标准强加的要求,即使它现在有效并且该要求对您来说没有意义。也庆幸有这么详细的标准

MPI 标准包含许多要求,但主要出于性能原因,这些要求通常不会被实现严格检查。基本原理是任何根据标准正确的程序在给定一组宽松的约束条件下也是正确的。依赖这种特定于实现的行为会导致代码不可移植并且违反标准。

有很多合理的理由要求不相交的发送段。立即可见的是与 MPI_Gatherv 的对称性。对于后者,段必须是不相交的,否则收集后的内存内容将取决于底层接收操作的顺序。由于在典型的 MPI 程序中,散点通常由聚集进行镜像,因此如果相同的约束适用于聚集和散点,则可以重复使用计算出的偏移量和计数数组。一个不太明显的原因是在某些体系结构上,网络设备可能不允许同时从重叠的内存区域读取。

由于非标准 MPI 行为很容易在开发过程中渗透到程序代码中,因此可能需要使用像我们的 MUST 这样的工具来检查程序的正确性。