c - 使用 MPI 在后台收听和回复

标签 c parallel-processing mpi

我想实现一个场景,其中一个进程有一些工作,并且系统中的所有其他进程向该进程发出请求。当然,这些其他进程不知道哪个进程有该作业,因此它们必须向每个其他进程发送消息并检查它们是否有作业。如果进程没有工作,他们会回复-1。当进程收到有作业要捐赠的进程的回复时,它将从中获取作业并忙于执行作业。但是,当它很忙时,如果它收到来自任何其他进程的请求,它将回复 -1。我一直无法让这个工作。到目前为止,我已经实现了 MPI_Send 和 MPI_Recv 的解决方案,如下所示:

 /* Master process has all the jobs to donate */
if(rank == MasterProcess)
   while(haveJobToDonate){
       /* listen to requests with MPI_ANY_SOURCE,MPI_ANY_TAG */
       MPI_Recv()
        /* when request received send a job to requesting process */
       MPI_Send()
   }
   /* if no job, then finish */

}else if(rank != MasterProcess){
     /* find a job */
     findJob()

}

findJob()方法如下:

findJob(){
   /*set target to 0 */
   while(JobNotFound){
      MPI_Send(target)
      MPI_Recv(fromTarget)
      /* if no job returned */
      if(req == -1)
         target += (target%NumberOfProcesses)
      else
         return req

   }

}

但是正如您可以猜到的,问题是如果一个进程没有作业,它就不会回复请求的进程,并且该进程将阻塞并等待。另一个问题是,如果一个进程得到了一份工作,它就会完成它的工作,而不会监听请求。如果一个进程发送了请求,那么它将阻塞并等待。这将使程序阻塞。 MPI 中是否有任何功能可以帮助解决这种情况?

最佳答案

您的问题的一些限制(例如问题中所解释的)对我来说有点太模糊,无法在答案中完全具体。例如,既然主进程是首先分配工作的进程,那么即使在分配了所有工作之后,为什么它不继续记录它,至少表明哪个进程拥有什么?这样,至少你想要更多工作的自由 worker 知道该从哪个其他 worker 那里窃取。

更好的是,我想你的工作最初是由 master 分批分配的(否则,一旦 master 完成分配,任何自由 worker 都知道没有什么可做的)。所以你可以看看the various schedule policies of OpenMP了解如何更改批处理来管理整体负载平衡。这个问题在 OpenMP 中非常常见,已经通过 schedule(guided) 得到了解决。这是一种您可以在主进程中轻松重新实现的解决方案,它避免了任何类型的工作人员之间的通信,因此比工作窃取更简单。

现在,假设窃取工作确实是您想要/需要做的,一种可能的解决方案是使用一些单方面的通信。每个工作人员都会在公开的内存窗口中记录其拥有的任务列表。然后,每当一个进程想要从中窃取一些工作时,它就会使用MPI_Win_lock()锁定该窗口,然后使用MPI_Compare_and_swap原子窃取任务(),最后使用MPI_Win_unlock()释放窗口。 MPI_Compare_and_swap() 的使用方式相当于将被探测的远程工作进程列表中的任务索引与当前进程想要窃取的任务进行比较。如果两者匹配,则这意味着该任务可以随意被窃取,并且当前进程会窃取该任务并通过已经完成的任何方式替换它,或者例如减去其等级以向任何其他即将到来的进程指示后来它现在拥有它......该操作的原子方面非常重要,因为另一个 worker 可以尝试在同一时间做同样的事情。如果没有原子探测和更新操作,来自不同进程的探测和更新操作可能会相互交错,从而导致错误的解决方案。

在此阶段,根据是否可以从当前工作人员刚刚获取的新任务中窃取某些工作,它必须使用 自动更新其自己的任务列表共享窗口>MPI_Win_lock() + MPI_Win_{put,accumulate,fetch_and_op}() + MPI_Win_unlock() 调用集。然后,它可以继续开始实际处理新获得的任务。

有关如何原子地使用这些单方面调用的简单示例,您可以查看 this answer .

注意,这仅从 MPI 3.0 开始可用。

关于c - 使用 MPI 在后台收听和回复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33849455/

相关文章:

c++ - 指针的初始化

正在运行的 python 代码停止运行

java - 在Java中重写进程类

c++ - 共享内存系统性能上的消息传递接口(interface)

c - execv* 并写入标准输入

c - i386-elf-gcc 输出关于 "static a = 0"的奇怪汇编命令

为 openwrt 编译 libstrope 以支持 TLS

c - OpenMP 中的高斯消除 - 无法并行化

c - MPI 派生数据类型

linux - 串行程序比并行 fortran 更快