我正在使用 mpi4py 在 Python 中运行 MPI 代码,如下所示:
from mpi4py import MPI
import numpy as np
import os
comm = MPI.COMM_WORLD
rank = comm.Get_Rank()
size = comm.Get_Size()
if rank == 0:
res = np.zeros(2**16)
jobs = os.listdir('/my/data/dir')
for i in xrange(len(jobs)):
proc = (i % (size - 1)) + 1 #lacks load balancing
buf = load_buf_from_file(job[i])
#root waits here at 100%
comm.Send([buf, dtype], dest = proc) #lacks load balancing
comm.Recv([res, dtype], source = MPI.ANY_SOURCE)
save_result_to_file(res)
else:
buf = np.zeros(2**16)
comm.Recv([buf, dtype], source = 0)
res = do_lots_of_work(buf)
comm.Send([res, dtype], dest = 0)
我注意到根进程总是很忙(CPU 为 100%)。我更喜欢让根进程休眠,直到工作进程准备好接收下一条消息。 MPI 编程中有哪些模式可以促进这种行为?也许根进程也应该在工作?
此设计中的另一个缺陷如下...如果工作进程 4 在 3 之前完成,则 4 必须等待 3 完成才能从 root 获取新消息才能继续工作。关于如何设计始终尝试将下一条消息发送到空闲进程的根进程有什么建议吗?这对我来说基本上没问题,因为第一个接收消息的进程通常是第一个完成的进程。但是,如果每条消息的工作负载发生变化,则情况并非总是如此。
谢谢, 凯文
最佳答案
关于你的第一个问题,关于 Comm.Recv 中排名 0 时的 CPU 使用情况。这是一个执行问题。 MPICH(可能还有许多其他)在紧密的轮询循环中等待事件,以最大限度地减少延迟。
您的第二个问题:如果工作单位不固定,如何平衡工作量。答案是非阻塞操作。 (Isend、Irecv 等)。
一种可能的工作流程可能如下所示:
- 等级 0 有一个工作单元队列
- 排名 0 向每个客户端发送非阻塞发送
- 当客户端需要工作时,它会从服务器接收并发回就绪消息
- 服务器获取就绪消息并发送工作单元。
- 服务器还会为最终的“我完成了”消息发出非阻塞接收。
- 当任何客户端完成时,它会发出“我完成了,给我更多”消息
- 服务器发送队列中的下一个工作单元。
关于python - MPI 中的设计模式 : sleep root process on blocking send and proper load balancing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25837051/