Python Mpi4py代码不会停止运行

Python Mpi4py代码不会停止运行,python,parallel-processing,cluster-computing,hpc,mpi4py,Python,Parallel Processing,Cluster Computing,Hpc,Mpi4py,我正在使用一个非常基本的python代码(文件名:test\u mpi.py)来尝试使用mpi4py在python中进行并行编程。我想做的是让一个二维numpy数组中的所有条目都为零。然后使用集群中的特定处理器来增加numpy数组中特定元素的值 具体来说,我有一个3*3numpy矩阵(mat),它的所有元素都是零。代码完成运行(跨多个处理器)后,我希望矩阵如下所示: mat = [[ 1. 2. 3.] [ 4. 5. 6.] [ 7. 8. 9.]]

我正在使用一个非常基本的python代码(文件名:
test\u mpi.py
)来尝试使用mpi4py在python中进行并行编程。我想做的是让一个二维numpy数组中的所有条目都为零。然后使用集群中的特定处理器来增加numpy数组中特定元素的值

具体来说,我有一个3*3numpy矩阵(
mat
),它的所有元素都是零。代码完成运行(跨多个处理器)后,我希望矩阵如下所示:

mat = [[ 1.  2.  3.]
       [ 4.  5.  6.]
       [ 7.  8.  9.]]
这是一个相当简单的任务,我希望我的代码在几分钟内(如果不是更短的时间)完成运行。我的代码持续运行很长一段时间,并且没有停止执行(最终我必须在数小时后删除作业)

这是我的代码:

from __future__ import division
from mpi4py import MPI
import os
import time
import numpy as np

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

start_time = time.time()

mat = np.zeros((3,3))

comm.bcast([ mat , MPI.DOUBLE], root=0)


for proc in range(1, nproc):
    if rank == proc:
        print "I'm processor: ", rank
        var = proc
        comm.send( var, dest=0, tag = (proc*1000) ) 
        print "Processor: ", rank, " finished working."


if rank == 0:
    print "Hello! I'm the master processor, rank: ", rank 
    for i in range(0,dim):
        for j in range(0, dim):
            proc = ((i*j)+1)
            mat[i,j] += comm.recv(source=proc, tag=(proc*1000) )


     np.savetxt('mat.txt', mat) 



print time.time() - start_time
这是我执行python代码的作业脚本:

#!/bin/sh

#PBS -l nodes=2:ppn=16
#PBS -N test_mpi4py
#PBS -m abe
#PBS -l walltime=168:00:00
#PBS -j eo
#PBS -q physics

cd $PBS_O_WORKDIR
export OMP_NUM_THREADS=16
export I_MPI_PIN=off
echo 'This job started on: ' `date`

/opt/intel/impi/2018.0.128/intel64/bin/mpirun -np 32 python test_mpi.py

我使用
qsub jobscriptname.sh
运行作业脚本。我错过了什么?我将非常感谢您的帮助。

您的代码没有完成,因为某些MPI通信没有完成

MPI要求每次发送应有一次接收。 您的第一个循环由每个MPI进程列组独立执行,除
0
rank外,每个列组的条件
rank==proc
将恰好满足一次,因此
comm.send
将执行
nproc-1
次。第二个循环执行
dim*dim
次。因此,
comm.recv
也将执行
dim*dim
次。除非
nproc-1==dim*dim
。该要求将无法满足,一些
recv
send
操作将无限期地等待完成。例如
31!=9
,因此在超过walltime之前,通信不会完成

为了纠正这个错误,让我们稍微澄清一下算法。所以我们想让从1到9的每一个秩负责3x3矩阵中的一个元素。每个进程级别发布
comm.send
请求。请求由进程秩0按一定顺序接收,并存储在矩阵的相应元素中。其余的队伍如果有空,什么也不做

让我们介绍三个变化:

  • 初始化
    dim的值
  • 移动条件运算符,检查处理器秩是否为0或是否超出循环
  • 修正当前不正确的元素
    mat[i,j]
    对应的秩的计算(例如,对于中心元素
    mat[1,1]
    秩应为5,而不是1*1+1=2)
  • 代码 以下是修改后的结果:

    from __future__ import division
    from mpi4py import MPI
    import os
    import time
    import numpy as np
    
    comm = MPI.COMM_WORLD
    nproc = comm.Get_size()
    rank = comm.Get_rank()
    
    start_time = time.time()
    
    dim = 3
    mat = np.zeros((dim,dim))
    
    comm.bcast([ mat , MPI.DOUBLE], root=0)
    
    if rank > 0:
        if rank <= dim * dim:
            print "I'm processor: ", rank
            var = rank
            req = comm.send( var, dest=0, tag = (rank*1000) )
        print "Processor: ", rank, " finished working."
    else:
        print "Hello! I'm the master processor, rank: ", rank 
        for i in range(0,dim):
            for j in range(0, dim):
                proc = ((i*dim)+j)+1
                if proc < nproc:
                    mat[i,j] += comm.recv(source=proc, tag=(proc*1000) )
        np.savetxt('mat.txt', mat)
    
    将以下矩阵保存到
    mat.txt

    1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00
    4.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00
    0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00
    
    1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00
    4.000000000000000000e+00 5.000000000000000000e+00 6.000000000000000000e+00
    7.000000000000000000e+00 8.000000000000000000e+00 9.000000000000000000e+00
    

    将以下矩阵保存到
    mat.txt

    1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00
    4.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00
    0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00
    
    1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00
    4.000000000000000000e+00 5.000000000000000000e+00 6.000000000000000000e+00
    7.000000000000000000e+00 8.000000000000000000e+00 9.000000000000000000e+00
    

    而10是能够产生正确结果的最小过程等级数。

    您的答案有效。非常感谢你的回答和精彩的解释。