MPI4PY大阵列散射产生死锁
MPI4PY big arrays scattering produce deadlock
我正在尝试使用 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
这里
对于大数组我必须使用 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]
,则代码有效。
任何人都可以建议我在这种情况下可以做什么吗?
一个问题是您混合了 np.float
和 MPI.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();
}
所以,最后,解决方案很简单——我通常不关闭我的电脑,这似乎是它在大量计算后产生死锁的原因。简单的重启解决了这个问题。
我正在尝试使用 Scatter()
:
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
这里
对于大数组我必须使用 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]
,则代码有效。
任何人都可以建议我在这种情况下可以做什么吗?
一个问题是您混合了 np.float
和 MPI.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();
}
所以,最后,解决方案很简单——我通常不关闭我的电脑,这似乎是它在大量计算后产生死锁的原因。简单的重启解决了这个问题。