Mpi4py代码不停运行
Mpi4py code does not stop running
我正在使用非常基本的 python 代码(文件名:test_mpi.py
)尝试使用 mpi4py 在 python 中进行并行编程。我想要做的是拥有一个所有条目都为零的二维 numpy 数组。然后使用集群中的特定处理器来增加 numpy 数组的特定元素的值。
具体来说,我有一个 3*3 numpy 矩阵 (mat
),它的所有元素都为零。在我的代码完成 运行ning(跨多个处理器)后,我希望矩阵看起来像这样:
mat = [[ 1. 2. 3.]
[ 4. 5. 6.]
[ 7. 8. 9.]]
这是一项相当简单的任务,我希望我的代码能够在几分钟内完成 运行ning(如果不是更短的时间)。我的代码保持 运行ning 很长时间并且不会停止执行(最终我不得不在几个小时后删除作业。)
这是我的代码:
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 进程级别独立执行,每个级别的条件 rank == proc
将只满足一次,但 0
级别除外,因此 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)
输出
这是输出:
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 是产生正确结果的最小进程等级数。
我正在使用非常基本的 python 代码(文件名:test_mpi.py
)尝试使用 mpi4py 在 python 中进行并行编程。我想要做的是拥有一个所有条目都为零的二维 numpy 数组。然后使用集群中的特定处理器来增加 numpy 数组的特定元素的值。
具体来说,我有一个 3*3 numpy 矩阵 (mat
),它的所有元素都为零。在我的代码完成 运行ning(跨多个处理器)后,我希望矩阵看起来像这样:
mat = [[ 1. 2. 3.]
[ 4. 5. 6.]
[ 7. 8. 9.]]
这是一项相当简单的任务,我希望我的代码能够在几分钟内完成 运行ning(如果不是更短的时间)。我的代码保持 运行ning 很长时间并且不会停止执行(最终我不得不在几个小时后删除作业。)
这是我的代码:
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 进程级别独立执行,每个级别的条件 rank == proc
将只满足一次,但 0
级别除外,因此 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)
输出
这是输出:
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 是产生正确结果的最小进程等级数。