Python HPC上的mpi4py:通信聚集

Python HPC上的mpi4py:通信聚集,python,mpi,hpc,mpi4py,Python,Mpi,Hpc,Mpi4py,我的目标是遍历大型2D数组(data)的每个元素,并对每个元素进行一些繁重的处理。因此,我希望使用多个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 =

我的目标是遍历大型2D数组(
data
)的每个元素,并对每个元素进行一些繁重的处理。因此,我希望使用多个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

非常感谢。

要澄清您在评论中为自己找到的答案:
MPI\u-Gather
是一个根操作:它的结果在所有列组中都不相同,并且在
参数中提供的列组上特别不同

聚集
的情况下,您发现秩0是以数据结尾的,这与您调用它的方式完全正确(使用
根=0

虽然原则上MPI支持多个程序、多个数据执行,其中不同的列组运行不同的代码,但实际上大多数MPI代码是以单个程序、多个数据样式编写的,就像您所编写的那样。因为所有列组都运行相同的代码体,所以在从根操作(如
MPI\u Gather
返回后,您需要检查正在运行的列组是否为根,并相应地执行不同的代码路径。如果不这样做,那么每个级别都将执行以下行:

print(np.shape(a_gath))
print('---') 
print(np.shape(b_gath))
正如您所注意到的,它不会打印您期望的
a_-gath
b_-gath
结果,排名0除外

请尝试以下操作:

a_gath = comm.gather(result_a, root=0)
b_gath = comm.gather(result_b, root=0)

if rank == 0:
    print(np.shape(a_gath))
    print('---')
    print(np.shape(b_gath))

为了澄清您在注释中找到的答案:
MPI\u Gather
是一个根操作:它的结果在所有级别上都不相同,并且在
root
参数中提供的级别上具体不同

聚集
的情况下,您发现秩0是以数据结尾的,这与您调用它的方式完全正确(使用
根=0

虽然原则上MPI支持多个程序、多个数据执行,其中不同的列组运行不同的代码,但实际上大多数MPI代码是以单个程序、多个数据样式编写的,就像您所编写的那样。因为所有列组都运行相同的代码体,所以在从根操作(如
MPI\u Gather
返回后,您需要检查正在运行的列组是否为根,并相应地执行不同的代码路径。如果不这样做,那么每个级别都将执行以下行:

print(np.shape(a_gath))
print('---') 
print(np.shape(b_gath))
正如您所注意到的,它不会打印您期望的
a_-gath
b_-gath
结果,排名0除外

请尝试以下操作:

a_gath = comm.gather(result_a, root=0)
b_gath = comm.gather(result_b, root=0)

if rank == 0:
    print(np.shape(a_gath))
    print('---')
    print(np.shape(b_gath))

他们只在等级上是空白的吗!=0?请创建一个包含如何执行的说明的文件。描述预期和实际结果。嗨,谢谢你的评论。我已经用更多的信息更新了这篇文章。希望这能让事情变得更清楚。不幸的是,我不能上传一个确切的例子。我的现实世界的输入数据和处理函数都太复杂,无法复制。希望这足够了。更详细的检查表明,@GillesGouaillardet,他们只是排名上的空白!=0我想我只是添加了一个条件语句,仅当秩==0时才将数据写入磁盘?这是一个术语上的挑剔:“我想使用多个MPI来分别获取阵列的一部分”——从上下文来看,您的用法似乎足够清楚,但我认为,在MPI术语中,这句话的意思是,您希望将工作分解到多个级别。是吗?他们只在等级上是空白的吗!=0?请创建一个包含如何执行的说明的文件。描述预期和实际结果。嗨,谢谢你的评论。我已经用更多的信息更新了这篇文章。希望这能让事情变得更清楚。不幸的是,我不能上传一个确切的例子。我的现实世界的输入数据和处理函数都太复杂,无法复制。希望这足够了。更详细的检查表明,@GillesGouaillardet,他们只是排名上的空白!=0我想我只是添加了一个条件语句,仅当秩==0时才将数据写入磁盘?这是一个术语上的挑剔:“我想使用多个MPI来分别获取阵列的一部分”——从上下文来看,您的用法似乎足够清楚,但我认为,在MPI术语中,这句话的意思是,您希望将工作分解到多个级别。是这样吗?