首页 文章

Mpi4py代码不会停止运行

提问于
浏览
0

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

具体来说,我有一个3 * 3的numpy矩阵( 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 来运行作业脚本 . 我在这里想念的是什么?我将在此感谢任何帮助 .

1 回答

  • 2

    您的代码未完成,因为某些MPI通信未完成 .

    MPI要求每次发送都应该只有一次接收 . 您的第一个循环由每个MPI进程排名独立执行,除了 0 rank之外,条件 rank == proc 将恰好满足每个排名一次,因此 comm.send 将被执行 nproc - 1 次 . 你的第二个循环执行 dim * dim 次 . 因此 comm.recv 也将执行 dim*dim 次 . 除非 nproc - 1 == dim * dim . 该要求不会得到满足,并且一些操作将等待无限期完成 . 对于您的示例 31 != 9 ,因此在超过挂起时间之前通信将无法完成 .

    为了解决这个错误,让我们澄清一下算法 . 因此,我们希望从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)
    

    输出

    这是输出:

    mpirun -np 5 python mpi4.py
    

    保存到 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
    

    mpirun -np 32 python mpi4.py
    

    保存到 mat.txt 以下矩阵

    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是产生正确结果的最小过程等级数 .

相关问题