python-3.x - 了解 mpi4py 中的 Put/Get
问题描述
我正在学习如何在 mpi4py 中使用单向通信。为了测试我的理解,我想出了这个人为的例子:
import mpi4py.MPI as mpi
import numpy as np
import time
def main():
rank = mpi.COMM_WORLD.Get_rank()
n_proc = mpi.COMM_WORLD.Get_size()
assert(n_proc == 2)
buff = np.zeros(10, dtype='d')
win = mpi.Win.Create(buff, 1, mpi.INFO_NULL, mpi.COMM_WORLD)
if (rank == 0):
win.Lock(1)
win.Put([buff, mpi.DOUBLE], 1)
win.Unlock(1)
buff[-1] = 9
time.sleep(30)
win.Lock(1)
win.Put([buff, mpi.DOUBLE], 1)
win.Unlock(1)
else:
holder = np.zeros(10)
failures = 0
while (holder[-1] != 9):
failures += 1
win.Lock(0)
win.Get([holder, mpi.DOUBLE], 0)
win.Unlock(0)
print('Took', failures, 'dials')
if __name__=='__main__':
main()
我希望它按如下方式工作:排名 0 将等待 30 秒,然后将包含的 ndarray[0, 0, ..., 0, 9]
放入共享内存。同时,rank 1 将不断检查 rank 0 是否更新了它的共享内存——一旦更新,它将打印出它看到的内容。具体来说,我希望 rank 1 会在 30 秒等待期间多次执行其 while 循环,而 rank 0 空闲。但是,当我使用 运行此代码时mpirun -n 2 python mwe.py
,我始终得到以下输出:
Took 2 dials
表明调用Get
只发生了两次。
具体问题:为什么只有两个Get
从 rank 1 调用?
更模糊的问题:我在这个 MWE 中是否犯了明显的错误?一般来说,我对 mpi4py/MPI 很陌生。
解决方案
如您所说,您正在创建一个共享内存窗口。该窗口授予通信器中的其他 MPI 进程直接访问存储您的确切内存的权限buff
。当您更改时,buff[-1] = 9
这当然会存储在所述内存中,并且窗口会立即受到影响。因此,Put
对本地进程(从 rank 0 到 rank 0)的显式调用是不必要的,并且Put
仅对将数据放置在远程内存窗口中有用。buff
其他 MPI 进程可以在排名 0 甚至开始其 30 秒的睡眠操作之前从窗口中读取您更改的变量。
不幸的是,您看到“Took 2 dials”的原因是因为 0 级和 1 级可能同时执行它们的第一个锁定和解锁,然后 0 级执行buff[-1] = 9
然后循环在 1 级上重复,它读取更新的缓冲区并退出2次迭代后。
PS:为了测试,先放个1s sleepbuff[-1] = 9
推荐阅读
- python - Discord 机器人命令不起作用(Discord.py)
- java - 如何使用 JFileChooser 和 JLabel 将图像上传到 JTextArea
- machine-learning - 两个堆叠的 LSTM 层之间有什么联系?
- arrays - Vue 返回观察者和数组
- mongodb - 我在一个对象中有一个数组,我试图在 Mongodb 的字符串中排除包含特定单词的值
- python - Python 字典,键为频率,值为字母
- for-loop - 如何在 Google AppScript 上根据条件推送最新输入的数据?
- string - Apache免费标记中的字符串比较
- python - 如何根据除零以外的其他值绘制.bar
- javascript - 在 React 中动态创建函数以供 react-router-dom 使用