在MPI中创建缓冲区的效率与开销通信

时间:2019-06-02 12:19:29

标签: parallel-processing mpi

我首先要声明,我不知道我对MPI缓冲区的假设或理解是否正确。如果不正确,则此问题很可能无效。我已经进行了必要的研究,我认为我的假设是合乎逻辑的。

请注意:下面有一个TL; DR。

假设: 这些是我对MPI Isends的理解:

  

定义:开始无阻塞发送
  int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request)

  1. 缓冲区只是对某些已分配内存的引用。
  2. 使用Isend,除非确认接收成功,否则不能安全地重用缓冲区。
  3. 通过为Isend的每个实例创建一个新的,内存分配的缓冲区,我们不会遇到缓冲区问题。
  4. 一个进程可以malloc一个缓冲区,发出它,继续工作,当它不得不再次发送时,它可以通过使用另一个malloc创建另一个缓冲区。
  5. 这些缓冲区(引用)可以存储在链接列表中,在终止检测得出所有匹配的发送和接收成功之后,这些列表可用于释放所有缓冲区。

背景:
我正在为一款名为Othello的游戏编写游戏AI。我正在使用不同的方法,但是在这里,我将重点介绍使用一种称为NegaScout(AlphaBeta / Minimax的变体)的技术。

我专门尝试随着过程数量的增加来提高效率。因此,我希望我的程序具有很高的可扩展性,并且实际上不关心少于8个内核的程序的性能。

我需要一种有效地平衡这些流程的负载的方法。 负载平衡的第一阶段相对容易。只需深入到有足够的树木供每个过程探索的深度即可。当一个进程在另一个之前完成搜索其树时,就会存在问题-负载平衡必须继续。这意味着我们必须在NegaScout算法内部实现负载平衡。

我首先使用主/从(或客户机/服务器)方法来处理动态负载平衡。但是,当流程必须彼此协作时,事情就变得棘手了。我不仅要处理一堆可用的工作,因为alpha beta值取决于每个递归调用中的值,或者取决于它们在树中的状态(板状态)。

我的理论是,如果使用阻塞发送,则可能会产生极大的通信开销。例如,如果我是一个必须将工作发送到请求流程的流程,则使用普通的阻塞发送效率低下,而普通的阻塞发送必须等待另一个可能正在探查其他通信标签的流程;例如TERMINATE_TAG。
我认为最重要的通信开销情况将出现在这里:

  1. 我是一个流程,P0,需要工作。
  2. 我从流程P1接收工作。
  3. 我做我的工作并收到答复。
  4. 我启动了阻止发送或非阻止发送:
    • 4.1。阻止发送使我可以向MPI_DOUBLE发送仅分配了一次的缓冲区。但是,现在我等待过程P1收到该消息,然后才能继续寻找工作。现在,过程P1可能处于其树的不同深度。这意味着它不能从P0接收答案,因为我们不能在该深度使用它。现在,P0被阻塞,直到P1返回到该深度。此外,这种情况可能会在多个深度发生多次,从而导致许多进程被阻塞。
    • 4.2。另一方面,如果我分配了答案缓冲区并指出应在标签中使用的答案深度,则可以使用缓冲区启动MPI_Isend。然后将该缓冲区的地址添加到我的缓冲区链接列表中,以在终止时解除分配。现在,答案是通过非阻塞发送发送的,我可以立即开始寻找更多工作,而不必等待P1处的接收。

这是工作量过大的过程的观点:

  1. 我,进程P1,一直使用MPI_Iprobe探测传入消息。
  2. 当我收到工作请求时,我决定是否发送该请求。
    • 2.1。如果我没有工作,我会分配一个整数缓冲区(任何一方都不会使用),将其添加到缓冲区的链接列表中以便以后释放,然后发送带有标签{{ 1}}或I_MAY_HAVE_WORK_LATER-视情况而定。非阻塞发送使我可以继续进行其他工作并处理其他传入通信,而不会造成瓶颈。
    • 2.2。如果确实有工作,我将对数据(电路板结构,当前深度和alpha-beta值)进行编码,然后将其分配到新缓冲区中。然后,我使用该缓冲区启动了另一个非阻塞发送,该缓冲区已添加到我的链表中。我可以立即继续我的工作并处理其他通信。
  3. 如果在那个特定深度到达工作列表的末尾,我现在必须从发送工作的过程中收集所有答案。假设我有一个计数器,用于指示将工作发送到的进程数。一些伪代码如下:
I_DONT_HAVE_WORK

现在我们有了一些背景,我终于可以问我一个问题:
假设我提出的动态缓冲策略有效,那么有效吗?在不断分配内存中进行权衡是否值得减少通信开销?
这种方法有一个明显的局限性。大量的缓冲区链接列表让我们假设我们有足够的内存来处理此问题。

很长的问题很抱歉。我只是想找到一种在所有流程中平衡负载的有效方法。

TL; DR:

  1. 创建内存并将其分配给MPI_Isend中使用的缓冲区,然后仅在终止时释放这些缓冲区是否完全可行?
  2. 不断分配缓冲区会如何影响程序的处理效率?
  3. 减少持续的通信探测会严重影响我的程序的性能吗?

我仍在尝试修复我的代码,因此我自己无法回答这些问题。我希望有更多经验的人可能会指出这种方法是否可行,从而节省一些时间。

非常感谢您阅读这个较长的问题! 任何建议将不胜感激。

0 个答案:

没有答案