[英]Mpi4py code does not stop running
我正在使用一個非常基本的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
來運行作業腳本。 我在這里錯過了什么? 我將在此感謝任何幫助。
您的代碼未完成,因為某些MPI通信未完成。
MPI要求每次發送都應該只有一次接收。 你的第一個循環由每個MPI進程排名獨立執行,條件rank == proc
將為每個排名完全滿足一次,除了0
rank,因此comm.send
將被執行nproc - 1
次。 你的第二個循環執行dim * dim
時間。 因此, comm.recv
也會在dim*dim
時候執行。 除非nproc - 1 == dim * dim
。 該要求不會得到滿足,一些recv
或send
操作將等待無限期完成。 對於您的示例31 != 9
,因此在超過壁壘時間之前通信將無法完成。
為了解決這個錯誤,讓我們稍微澄清一下算法。 因此,我們希望讓1到9中的每個等級負責3x3矩陣中的一個元素。 每個流程排名發布comm.send
請求。 通過進程等級0以特定順序接收請求並將其存儲在矩陣的對應元素中。 其余的隊伍如果可用則什么都不做。
讓我們介紹三個變化:
dim
的值 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是產生正確結果的最小數量的過程等級。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.