【问题标题】:MPI4PY big arrays scattering produce deadlockMPI4PY大阵列散射产生死锁
【发布时间】:2020-03-11 21:15:28
【问题描述】:

我正在尝试使用 Scatter() 在 3 个进程之间分散一个大小为 (3,512,512,48,2) 且数据类型为双精度 np.float64 的数组:

# mpirun -np 3 python3 prog.py
import numpy as np
from mpi4py import MPI

if __name__ == "__main__":
 comm = MPI.COMM_WORLD
 nproc = comm.Get_size()
 rank = comm.Get_rank()  
 a = None

 a_split = np.empty([512,512,48,2],dtype = np.float64)


 if rank==0:

     a = np.zeros([3,512,512,48,2],dtype = np.float64)

     print(a.shape)

 comm.Barrier()

 print('Scattering')


 comm.Scatter([a, MPI.DOUBLE], a_split, root = 0)

但是,程序出现死锁。根据我从这里找到的内容

mpi4py scatter and gather with large numpy arrays

这里

Along what axis does mpi4py Scatterv function split a numpy array?

对于大数组,我必须使用Scatterv() 函数。所以,这里是另一个使用这个函数的代码:

# mpirun -np 3 python3 prog.py
import numpy as np
from mpi4py import MPI

if __name__ == "__main__":
    comm = MPI.COMM_WORLD
    nproc = comm.Get_size()
    rank = comm.Get_rank()  
    a = None

    a_split = np.empty([512,512,48,2],dtype = np.float64)

    size = 512*512*48*2 

    if rank==0:

        a = np.zeros([3,512,512,48,2],dtype = np.float64)

        print(a.shape)

    comm.Barrier()

    print('Scattering')

    comm.Scatterv([a,(size,size,size),(0,size,2*size),MPI.DOUBLE],a_split,root =0)

然而,这也会导致死锁。我还尝试使用与Send(),Recv() 的点对点通信发送数组,但这没有帮助。似乎死锁仅取决于数组大小 - 例如,如果我将数组大小从 [512,512,48,2] 更改为 [512,10,48,2],则代码有效。

谁能建议我在这种情况下可以做什么?

【问题讨论】:

    标签: python arrays numpy mpi mpi4py


    【解决方案1】:

    一个问题是您将np.floatMPI.DOUBLE 混合使用。 一个工作脚本可以是:

    # mpirun -np 3 python3 prog.py
    import numpy as np
    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    nproc = comm.Get_size()
    rank = comm.Get_rank()  
    a = None
    
    a_split = np.empty([512,512,48,2],dtype = np.float)
    a_split[:,:,:,:] = -666
    
    if rank==0:
        a = np.zeros([3,512,512,48,2],dtype = np.float)
        print(a.shape)
    
    print('Scattering')
    comm.Scatter(a, a_split, root = 0)
    
    print(a_split[1,1,1,1], a_split[-1,-1,-1,-1])
    

    我添加了最后一行以显示 -np 4 可以工作,但不能完全填满 a_split ;和 -np 2 失败并出现截断错误。我的猜测是 -np 3 是故意的。

    如果您有意使用 np.float 和 MPI.DOUBLE ,请在您的问题中提及并添加您用于启动程序的 -np

    [编辑] 这里也是你的脚本的 C++ 版本,所以你可以看看它是否也死锁:

    // mpic++ scat.cxx && mpirun -np <asmuchasyouwant> ./a.out
    
    #include <iostream>
    #include <vector>
    #include <mpi.h>
    
    int main(int argc, char** argv)
    {
      MPI_Init(&argc, &argv);
    
      unsigned sz = 1*512*512*48*2;
      int rank, nbproc;
      std::vector<double> a;
      std::vector<double> a_split(sz);
    
      MPI_Comm_rank(MPI_COMM_WORLD, &rank);
      MPI_Comm_size(MPI_COMM_WORLD, &nbproc);
    
      if (rank == 0) {
        a.resize(nbproc * sz);
        std::fill(a.begin(), a.end(), 2.71);
      }
      else {
        std::fill(a_split.begin(), a_split.end(), -666.666);
      }  
    
      MPI_Scatter(a.data(), sz, MPI_DOUBLE,
                  a_split.data(), sz, MPI_DOUBLE,
                  0,
                  MPI_COMM_WORLD
                  );
    
    
      std::cout << rank << " done " << a_split[sz-1] << std::endl;
    
      MPI_Finalize();
    }
    

    【讨论】:

    • 感谢您的回复! floatdouble 的混合不是故意的,所以我编辑了问题以获得正确的代码。不幸的是,由于某种原因,您提供的代码也停留在“分散”状态,并且再次使用较小的数组,代码可以正常工作。
    • 我的mpi4py.__version__2.0.0,没有死锁。您在使用其他版本吗?
    • 另外,你在 python 之外也有同样的死锁,带有 c++ scatter 吗?
    • 我已经尝试过 c++ 代码 - 它工作正常,没有任何死锁。我的 mpi4py 版本是 3.0.2,所以我想我会尝试安装 2.0.0 来检查它是否有效。
    • 我还要检查你的 python 安装找到了哪个 libmpi.so(顺便说一句,你是在 Linux 下还是 windows 下?)
    【解决方案2】:

    所以,最后,解决方案非常简单——我通常不会关闭我的电脑,这似乎就是它在大量计算后产生死锁的原因。简单的重启解决了这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-21
      • 2020-07-31
      • 2021-03-12
      • 1970-01-01
      • 2013-12-28
      • 2013-03-06
      • 1970-01-01
      • 2011-05-04
      相关资源
      最近更新 更多