我的目标是遍历大型2D数组(data
)的每个元素,并对每个元素进行一些繁重的处理。因此,我想使用多个mpi,每个mpi占用阵列的一部分。我遇到的问题是,我不知道如何准确地编写代码,以便在最后收集所有数据。下面是一些示例代码:
import numpy as np
import math
from mpi4py import MPI
M = 400
N = 300
data = np.random.rand(M,N)
result_a = np.zeros((M,N))
result_b = np.zeros((M,N))
def process_function(data):
a = data**2
b = data**0.5
return a,b
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
minimum = 0
maximum = int(M*N)
perrank = maximum//size
for index in range(minimum + rank*perrank, minimum + (rank+1)*perrank):
i = int(math.floor(index/N))
j = int(index % N)
a,b = process_function(data[i,j])
result_a[i,j] = a
result_b[i,j] = b
a_gath = comm.gather(result_a, root=0)
b_gath = comm.gather(result_b, root=0)
print(np.shape(a_gath))
print('---')
print(np.shape(b_gath))
不幸的是,对于我真正的问题,当我将a_gath
和b_gath
都保存到磁盘(作为pickle)时,当我重新加载它们时,它们只包含一次()
(即类型None
)。在comm.gather
之前/之后还有什么我应该做的吗?你知道吗
以下是我的提交脚本:
#!/bin/bash -l
#$ -S /bin/bash
#$ -l h_rt=00:05:00
#$ -l mem=2G
#$ -l tmpfs=10G
#$ -pe mpi 5
#$ -N stack_test
#$ -notify
#$ -wd /home/user/Scratch/
module load gcc-libs
module load python3/recommended
module unload compilers mpi
module load compilers/gnu/4.9.2
module load mpi/openmpi/3.1.1/gnu-4.9.2
module load mpi4py
module list
python_infile=test.py
echo ""
echo "Running python < $python_infile ..."
echo ""
gerun python $python_infile
我提交这个脚本时只使用qsub js_test.sh
这个伪示例返回的.o文件显示,在本例中,4/5 mpi包含类型None
信息:在本例中,如果我将a_gath
和b_gath
保存到磁盘,它会保存最后一个mpi吗?哪种类型是None
?我希望在使用comm.gather
之后,对于变量a_gath
和b_gath
,我会有一个大小为MxN
的数组
()
---
()
()
---
()
()
---
()
(5, 400, 300)
---
(5, 400, 300)
()
---
()
非常感谢。你知道吗
为了澄清您在注释中找到的答案:
MPI_Gather
是一个根操作:它的结果在所有等级中都不相同,并且在root
参数中提供的等级上特别不同。你知道吗在
Gather
的情况下,您发现秩0是以数据结尾的,这与您调用它的方式完全正确(使用root=0
)。你知道吗虽然原则上MPI支持不同列组运行不同代码的多程序、多数据执行,但实际上大多数MPI代码都是以单程序、多数据的方式编写的,就像您编写的那样。因为所有列组都运行相同的代码体,所以在从根操作(如
MPI_Gather
)返回后,您需要检查正在运行的列组是否是根,并相应地执行不同的代码路径。如果你不这样做,那么每个等级都将执行以下命令:正如您所注意到的,它不会打印您所期望的
a_gath
和b_gath
的结果,除了秩0。你知道吗请尝试以下操作:
相关问题 更多 >
编程相关推荐