C++ 使用MPI的不平衡负载(v2.0)

C++ 使用MPI的不平衡负载(v2.0),c++,dynamic,mpi,C++,Dynamic,Mpi,这个问题令人尴尬地平行出现 考虑一个由12个单元组成的数组: |__|__|__|__|__|__|__|__|__|__|__|__| 和四个4 CPU 天真地,我会运行4个并行作业,并为每个CPU提供3个单元 |__|__|__|__|__|__|__|__|__|__|__|__| =========|========|========|========| 1 CPU 2 CPU 3 CPU 4 CPU 但是,似乎每个单元都有不同的计算时间,有些单元的计算速度非

这个问题令人尴尬地平行出现

考虑一个由12个单元组成的数组:

|__|__|__|__|__|__|__|__|__|__|__|__|
和四个4 CPU

天真地,我会运行4个并行作业,并为每个CPU提供3个单元

|__|__|__|__|__|__|__|__|__|__|__|__|
=========|========|========|========|
   1 CPU    2 CPU    3 CPU    4 CPU
但是,似乎每个单元都有不同的计算时间,有些单元的计算速度非常快,有些则不然

因此,我认为不要浪费松弛的CPU,而是一次将每个单元提供给每个CPU,并继续执行,直到完成整个任务

即:

开始时:

|____|____|____|____|____|____|____|____|____|____|____|____|
 1cpu 2cpu 3cpu 4cpu
如果2cpu在第2单元完成工作,它可以跳转到第一个空的第5单元并继续工作:

|____|done|____|____|____|____|____|____|____|____|____|____|
 1cpu      3cpu 4cpu 2cpu
       |-------------->
如果1cpu完成,则可能需要第六个单元:

|done|done|____|____|____|____|____|____|____|____|____|____|
           3cpu 4cpu 2cpu 1cpu 
  |------------------------>
依此类推,直到完成完整数组

问题:

我不知道哪个单元是快的,哪个单元是慢的,所以我不能根据负载分配CPU—更多的CPU变慢,更少的CPU变快。 如何用MPI实现这种动态评估算法

谢谢

更新

我使用一种非常简单的方法,即如何使用IO-MPI将整个作业划分为块:

给定:阵列[NNN]和NPROC-可用工作单元数:

for (int i=0;i<NNN/nprocs;++i)
{
  do_what_I_need(start+i);
}
MPI_File_write(...);
其中start对应于特定的秩编号。简单地说,我根据可用CPU的数量将整个NNN数组划分为固定大小的块,每个CPU执行其块,将结果写入公共输出并释放

是否可以按照主/从模式将代码更改为不完全重写,这样每个CPU将只获得一次迭代,而不是NNN/NPROC,并且在完成其工作并将其部分写入文件后,将继续到下一个单元,而不是放松


谢谢

有一种众所周知的并行编程模式,有许多名称,其中一些是:任务包、主/工作者、任务农场、工作池等。其思想是拥有一个单一的主进程,将单元分配给其他工作者。每个worker运行一个无限循环,在这个循环中,它等待来自master的消息,计算一些内容,然后返回结果。通过让主机发送带有特殊标记的消息来终止循环。工作人员可以使用通配符标记值MPI_ANY_标记来接收具有不同标记的消息

大师更复杂。它还运行一个循环,但直到处理完所有单元格。最初,它向每个工作者发送一个单元格,然后开始一个循环。在这个循环中,它使用MPI_any_source的通配符source值从任何worker接收消息,如果有更多的单元格要处理,则将其中一个发送给返回结果的同一个worker。否则,它将发送一条标记设置为终止值的消息


在互联网上有许多这种模型的现成实现,例如,甚至还有一些在堆栈溢出上的实现。请注意,此方案需要一个额外的MPI进程,该进程通常只做很少的工作。如果这是不可接受的,则可以在单独的线程中运行辅助循环。

有一种众所周知的并行编程模式,有许多名称,其中一些名称是:任务包、主/辅助、任务场、工作池等。其思想是使用单个主进程,将单元分配给其他辅助进程。每个worker运行一个无限循环,在这个循环中,它等待来自master的消息,计算一些内容,然后返回结果。通过让主机发送带有特殊标记的消息来终止循环。工作人员可以使用通配符标记值MPI_ANY_标记来接收具有不同标记的消息

大师更复杂。它还运行一个循环,但直到处理完所有单元格。最初,它向每个工作者发送一个单元格,然后开始一个循环。在这个循环中,它使用MPI_any_source的通配符source值从任何worker接收消息,如果有更多的单元格要处理,则将其中一个发送给返回结果的同一个worker。否则,它将发送一条标记设置为终止值的消息


在互联网上有许多这种模型的现成实现,例如,甚至还有一些在堆栈溢出上的实现。请注意,此方案需要一个额外的MPI进程,该进程通常只做很少的工作。如果这是不可接受的,则可以在单独的线程中运行worker循环。

您希望实现一种客户机-服务器体系结构,在这种体系结构中,当工作人员失业时,他们会向服务器请求工作


根据数据块的大小以及工作人员与服务器之间的通信速度,您可能需要调整发送给工作人员的数据块的大小。

您需要实现一种客户机-服务器体系结构,在这种体系结构中,工作人员在下班时向服务器请求工作

根据数据块的大小以及工作人员与服务器之间的通信速度,您可能需要调整发送给工作人员的数据块的大小。

回答 你的最新问题:


在主/从或工作池下,如果您希望将其标记为model,则基本上需要一个任务调度器。船长应了解已完成的工作和仍需完成的工作。主进程将给每个进程一些要做的工作,然后使用非阻塞接收和wait_all等待进程完成。一旦流程完成,让它将数据发送给主机,然后等待主机以更多的工作响应。继续此操作直到工作完成。

要回答更新的问题:



在主/从或工作池下,如果您希望将其标记为model,则基本上需要一个任务调度器。船长应了解已完成的工作和仍需完成的工作。主进程将给每个进程一些要做的工作,然后使用非阻塞接收和wait_all等待进程完成。一旦流程完成,让它将数据发送给主机,然后等待主机以更多的工作响应。继续此操作,直到工作完成。

在Windows API中,存在一个函数tryInterCriticalSection,可用于创建您描述的行为。我没有使用MPI的经验,但它可能有类似的功能。@quinxorin,我使用GNU并在linux HPC集群上工作,所以我不能使用它。但是谢谢你的建议!在Windows API中,存在一个函数TryEnterCriticalSection,可用于创建您描述的行为。我没有使用MPI的经验,但它可能有类似的功能。@quinxorin,我使用GNU并在linux HPC集群上工作,所以我不能使用它。但是谢谢你的建议!谢谢是的,我正在寻找一种工人池解决方案,因此我想知道,是否有好的MPI实现。我了解一个逻辑,它应该如何工作,并且拥有大量可用资源,拥有1024个CPU的群集,因此一个额外的MPI进程是可以的。请查看主题的更新和我的问题。谢谢!是的,我正在寻找一种工人池解决方案,因此我想知道,是否有好的MPI实现。我理解一个逻辑,它应该如何工作,并且有大量可用资源群集1024个CPU,因此一个额外的MPI进程是可以的。请参阅主题的更新和我的问题。确实,但我不知道先验,哪个块是耗时的。这就是为什么每个工作人员只分配问题的一小部分,例如,你的问题中有一个单元格。我对区块大小评论的意思很简单,如果您的单元格太小,以至于与工作人员通信的开销超过了您的单元格的实际工作,那么您应该一次发送多个单元格。请参阅主题更新和我的新问题。谢谢您需要某种方法来动态地将单元格分配给进程,因为您事先不知道每个单元格的工作量。就我所知,使用客户机-服务器模型是最简单的解决方案。事实上,但我不知道哪一个块需要花费时间。这就是为什么每个工作人员只分配问题的一小部分,例如,问题中的一个单元格。我对区块大小评论的意思很简单,如果您的单元格太小,以至于与工作人员通信的开销超过了您的单元格的实际工作,那么您应该一次发送多个单元格。请参阅主题更新和我的新问题。谢谢您需要某种方法来动态地将单元格分配给进程,因为您事先不知道每个单元格的工作量。据我所知,使用客户机-服务器模型是最简单的解决方案。谢谢!我会努力实现它!非常感谢。我会努力实现它!