Python 3.x mpi4py中的共享内存

Python 3.x mpi4py中的共享内存,python-3.x,mpi,shared-memory,mpi4py,memoryview,Python 3.x,Mpi,Shared Memory,Mpi4py,Memoryview,我使用一个MPI(mpi4py)脚本(在单个节点上),它可以处理非常大的对象。为了让所有进程都能访问该对象,我通过comm.bcast()分发它。这会将对象复制到所有进程,并消耗大量内存,尤其是在复制过程中。因此,我想分享一些东西,比如指针,而不是对象本身。我发现memoryview中的一些功能对于提高进程内对象的工作效率非常有用。此外,对象的实际内存地址可通过memoryview对象字符串表示法访问,并可按如下方式分布: from mpi4py import MPI comm = MPI.C

我使用一个
MPI
mpi4py
)脚本(在单个节点上),它可以处理非常大的对象。为了让所有进程都能访问该对象,我通过
comm.bcast()
分发它。这会将对象复制到所有进程,并消耗大量内存,尤其是在复制过程中。因此,我想分享一些东西,比如指针,而不是对象本身。我发现
memoryview
中的一些功能对于提高进程内对象的工作效率非常有用。此外,对象的实际内存地址可通过
memoryview
对象字符串表示法访问,并可按如下方式分布:

from mpi4py import MPI

comm = MPI.COMM_WORLD
rank = comm.Get_rank()

if rank:
    content_pointer = comm.bcast(root = 0)
    print(rank, content_pointer)
else:
    content = ''.join(['a' for i in range(100000000)]).encode()
    mv = memoryview(content)
    print(mv)
    comm.bcast(str(mv).split()[-1][: -1], root = 0)
这张照片是:

<memory at 0x7f362a405048>
1 0x7f362a405048
2 0x7f362a405048
...

1 0x7f362a405048
2 0x7f362a405048
...
这就是为什么我相信一定有办法在另一个过程中重建对象。但是,我在文档中找不到关于如何操作的线索


简而言之,我的问题是:是否可以在
mpi4py
中的同一节点上的进程之间共享对象?

我对mpi4py了解不多,但从MPI的角度来看,这应该是不可能的。MPI代表消息传递接口,它的确切含义是:在进程之间传递消息。您可以尝试使用类似于全局可访问内存的东西,但其他进程无法使用进程内存


如果您需要依赖一大块共享内存,则需要利用OpenMP或线程之类的功能,这些功能绝对可以在单个节点上使用。使用MPI和一些共享内存并行化的混合并行化将允许每个节点有一个共享内存块,但仍然可以选择使用多个节点。

下面是一个使用MPI的共享内存的简单示例,从

您可以使用以下工具运行它:
mpirun-n2 python3 shared\u memory\u test.py
(假设您将其保存为shared\u memory\u test.py)

应输出(从流程等级0打印):


鉴于MPI 3.0共享内存()@BenThompson,此答案不正确。好的,要我删除它或更改答案吗?我对这个新功能没有经验…多维数组呢,比如说np.zeros((50,50,50))?@Zézouille对于多维数组,它是类似的,你只需要(大约)做以下更改:
size=1000
shape=(50,50,50)
size=np.prod(shape)
这一行变成
ary=np.ndarray(buffer=buf,dtype='d',shape=shape)#而不是shape=(size,)
并且要运行这个特定的示例,您还需要将
ary[:5]=np.arange(5)
更改为
ary[:5,1,1]=np.arange(5)
print(ary[:10])
更改为
print(ary[:10,1,1])
@JobJob你知道词典是否可以做到这一点吗?你能接受JobJob的新MPI 3.0答案是正确的吗?
from mpi4py import MPI 
import numpy as np 

comm = MPI.COMM_WORLD 

# create a shared array of size 1000 elements of type double
size = 1000 
itemsize = MPI.DOUBLE.Get_size() 
if comm.Get_rank() == 0: 
    nbytes = size * itemsize 
else: 
    nbytes = 0

# on rank 0, create the shared block
# on rank 1 get a handle to it (known as a window in MPI speak)
win = MPI.Win.Allocate_shared(nbytes, itemsize, comm=comm) 

# create a numpy array whose data points to the shared mem
buf, itemsize = win.Shared_query(0) 
assert itemsize == MPI.DOUBLE.Get_size() 
ary = np.ndarray(buffer=buf, dtype='d', shape=(size,)) 

# in process rank 1:
# write the numbers 0.0,1.0,..,4.0 to the first 5 elements of the array
if comm.rank == 1: 
    ary[:5] = np.arange(5)

# wait in process rank 0 until process 1 has written to the array
comm.Barrier() 

# check that the array is actually shared and process 0 can see
# the changes made in the array by process 1
if comm.rank == 0: 
    print(ary[:10])
[0. 1. 2. 3. 4. 0. 0. 0. 0. 0.]