【问题标题】:Wait until slaves called MPI_finalize等到奴隶调用 MPI_finalize
【发布时间】:2023-04-08 03:11:01
【问题描述】:

我对以下代码有疑问:

大师:

#include <iostream> 
using namespace std;

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define PB1 1
#define PB2 1

int main (int argc, char *argv[])
{
  int np[2] = { 2, 1 }, errcodes[2];
  MPI_Comm parentcomm, intercomm;
  char *cmds[2] = { "./slave", "./slave" };
  MPI_Info infos[2] = { MPI_INFO_NULL, MPI_INFO_NULL };  
  MPI_Init(NULL, NULL);

#if PB1
  for(int i = 0 ; i<2 ; i++)
    {
      MPI_Info_create(&infos[i]);      
      char hostname[] = "localhost";
      MPI_Info_set(infos[i], "host", hostname);
    }
#endif

  MPI_Comm_spawn_multiple(2, cmds, MPI_ARGVS_NULL, np, infos, 0, MPI_COMM_WORLD, &intercomm, errcodes);  
  printf("c Creation of the workers finished\n");

#if PB2
  sleep(1);
#endif

  MPI_Comm_spawn_multiple(2, cmds, MPI_ARGVS_NULL, np, infos, 0, MPI_COMM_WORLD, &intercomm, errcodes);
  printf("c Creation of the workers finished\n");

  MPI_Finalize();
  return 0;
}

从机:

#include "mpi.h"
#include <stdio.h>

using namespace std;

int main( int argc, char *argv[])
{
  int rank;
  MPI_Init(0, NULL);

  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  printf("rank =  %d\n", rank);

  MPI_Finalize();  
  return 0;
}

我不知道为什么当我运行 mpirun -np 1 ./master 时,当我将 PB1 和 PB2 设置为 1 时,我的程序会停止并显示以下消息(当我设置他们为0):

系统中没有足够的可用插槽来满足 2 应用程序请求的插槽:./slave 要么 为您的应用程序请求更少的插槽,或提供更多可用的插槽 供使用。

例如,当我将 PB2 设置为 0 时,程序运行良好。因此,我想这是因为 MPI_finalize 没有完成它的工作......

我用谷歌搜索,但没有找到任何问题的答案。我尝试了各种方法:调用 MPI_comm_disconnect,添加障碍,......但没有任何效果。

我在 Ubuntu (15.10) 上工作并使用 OpenMPI 版本 1.10.2。

【问题讨论】:

  • 我不确定这是否能回答您的问题,但您不能 MPI_Finalize 连接进程的子集。 “MPI_Finalize 是所有已连接进程的集体。[...] 它是所有已连接和继续连接的进程的联合。”。在你打电话给主人MPI_Finalize之前,你的第一批奴隶永远不会完成。你可以MPI_Comm_disconnectsee here - 不确定你到底尝试了什么。
  • 我非常感谢您的最小示例,但在这种情况下,了解您最终想要实现的目标可能会有所帮助。你的产卵药膏的概念可能经过深思熟虑,也可能没有经过深思熟虑,可能有也可能没有更好的选择。这也取决于您的实际用例。如果这是例如批处理系统,那么无论如何获取动态资源都不会有任何乐趣。
  • 我的目标是实现一个调用外部软件来解决子问题(约束满足问题)的应用程序。在这个应用程序中,slave 必须与 master 进行大量通信。
  • 你有控制外部软件还是那些黑匣子?您设想如何与外部软件进行通信?
  • 它并不是真正的黑盒。但是,我更喜欢限制修改以使软件用户友好(对于非专业人士)。

标签: c mpi openmpi


【解决方案1】:

在主服务器上调用 MPI_Finalize 之前,第一组 salve 上的 MPI_Finalize 不会完成。 MPI_Finalize 是所有连接进程的集合。您可以通过在调用MPI_Finalize 之前手动断开第一批药膏与互通器的连接来解决此问题。这样,slave 将真正完成并退出 - 为新一批 slave 释放“槽”。不幸的是,我没有看到一种标准化的方法来真正确保从属设备完成,因为它们的插槽被释放,因为这将是实现定义的。 OpenMPI 在MPI_Comm_spawn_multiple 中冻结而不是返回错误这一事实是不幸的,人们可能会认为这是一个错误。无论如何,这是您可以做的草稿:

在主服务器中,每次都由它的从服务器完成:

MPI_Barrier(&intercomm); // Make sure master and slaves are somewhat synchronized
MPI_Comm_disconnect(&intercomm);
sleep(1); // This is the ugly unreliable way to give the slaves some time to shut down

奴隶:

MPI_Comm parent;
MPI_Comm_get_parent(&parent); // you should have that already
MPI_Comm_disconnect(&parent);
MPI_Finalize();  

但是,您仍然需要确保 OpenMPI 知道应该为整个应用程序保留多少个插槽 (universe_size)。例如,您可以使用hostfile

localhost slots=4

然后是mpirun -np 1 ./master

现在这并不漂亮,我认为您动态生成 MPI 工作人员的方法并不是 MPI 的真正用途。标准可能支持它,但如果实现遇到困难,这对您没有帮助。但是,没有足够的信息说明您打算如何与外部进程进行通信以提供更清晰、更符合理念的解决方案。

最后一点:一定要检查 MPI 函数的返回码。尤其是MPI_Comm_spawn_multiple

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    相关资源
    最近更新 更多