【问题标题】:Shared memory in mpi4pympi4py 中的共享内存
【发布时间】:2015-12-05 18:02:10
【问题描述】:

我使用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
...

这就是为什么我相信必须有一种方法可以在另一个过程中重构对象。但是,我在文档中找不到有关如何执行此操作的线索。

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

【问题讨论】:

  • 您能接受 JobJob 的新 MPI 3.0 答案正确吗?

标签: python-3.x mpi shared-memory mpi4py memoryview


【解决方案1】:

这是一个使用 MPI 的共享内存的简单示例,对 https://groups.google.com/d/msg/mpi4py/Fme1n9niNwQ/lk3VJ54WAQAJ 稍作修改

您可以使用:mpirun -n 2 python3 shared_memory_test.py 运行它(假设您将其保存为 shared_memory_test.py)

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 打印):

[0. 1. 2. 3. 4. 0. 0. 0. 0. 0.]

【讨论】:

  • 多维数组怎么样,比如说 np.zeros((50, 50, 50))?
  • @Zézouille 对于多维数组,它是相似的,您只需(大约)进行以下更改:size = 1000shape = (50,50,50)size = np.prod(shape) 并且此行变为 ary = np.ndarray(buffer=buf, dtype='d', shape=shape) # instead of shape=(size,) 和要运行此特定示例,您还需要将 ary[:5] = np.arange(5) 更改为 ary[:5, 1, 1] = np.arange(5)print(ary[:10]) 更改为 print(ary[:10, 1, 1])
  • @JobJob 你知道字典是否可以实现吗?
【解决方案2】:

我对 mpi4py 了解不多,但从 MPI 的角度来看,这应该是不可能的。 MPI 代表消息传递接口,这意味着:在进程之间传递消息。您可以尝试使用MPI One-sided communication 来模拟全局可访问内存,但其他进程无法使用进程内存。

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

【讨论】:

  • 鉴于 MPI 3.0 共享内存 (software.intel.com/en-us/articles/…),此答案不正确
  • @BenThompson 好的,您要我删除它还是更改答案?我有 0 次使用此新功能的经验...
猜你喜欢
  • 1970-01-01
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 2011-12-04
  • 1970-01-01
  • 2014-03-22
  • 2012-07-29
相关资源
最近更新 更多