MPI Spawn:根进程不与子进程通信

(初学者问题)我正在尝试使用MPI_Comm_Spawn动态生成进程,然后向子进程广播消息,但程序在从根进程到子进程的广播中停止。 我正在关注http://www.mpi-forum.org/docs/docs.html上的文档,但我无法使其工作。 有人可以帮帮我吗?

#include  #include  int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); MPI_Comm parentcomm; MPI_Comm_get_parent( &parentcomm ); if (parentcomm == MPI_COMM_NULL) { MPI_Comm intercomm; MPI_Status status; char msg_rec[1024]; char msg_send[1024]; int size, i; int np = (argc > 0) ? atoi(argv[1]) : 3; printf("Spawner will spawn %d processes\n", np); MPI_Comm_spawn( argv[0], MPI_ARGV_NULL, np, MPI_INFO_NULL, 0, MPI_COMM_SELF, &intercomm, MPI_ERRCODES_IGNORE ); MPI_Comm_size(intercomm, &size); sprintf(msg_send, "Hello!"); printf("Spawner will broadcast '%s'\n", msg_send); MPI_Bcast( (void*)msg_send, 1024, MPI_CHAR, 0, intercomm); printf("Spawner will receive answers\n"); for (i=0; i < size; i++) { MPI_Recv( (void*)msg_rec, 1024, MPI_CHAR, i, MPI_ANY_TAG, intercomm, &status); printf("Spawner received '%s' from rank %d\n", msg_rec, i); }; } else { int rank, size; char msg_rec[1024]; char msg_send[1024]; MPI_Comm_rank(parentcomm, &rank); MPI_Comm_size(parentcomm, &size); printf(" Rank %d ready\n", rank); MPI_Bcast( (void*)msg_rec, 1024, MPI_CHAR, 0, parentcomm); printf(" Rank %d received '%s' from broadcast!\n", rank, msg_rec); sprintf(msg_send, "Hi there from rank %d!\n", rank); MPI_Send( (void*)msg_send, 1024, MPI_CHAR, 0, rank, parentcomm); }; MPI_Finalize(); return 0; }; 

我不知道它是否重要,但我使用的是ubuntu 11.10和Hidra Process Manager。

正如@suszterpatt指出的那样,你正在使用“Intercommunicator”(不是“内部通信器”)。 了解这一点并查看MPI_Bcast ,我们看到:

如果comm是一个内部通信器,那么该调用涉及内部通信器中的所有进程,但是一个组(组A)定义了根进程。 另一组(组B)中的所有进程在参数root中传递相同的值,该值是组A中的根的等级。根在根中传递值MPI_ROOT。 组A中的所有其他进程都以root身份传递值MPI_PROC_NULL。 数据从根广播到组B中的所有进程。组B中进程的接收缓冲区参数必须与根的发送缓冲区参数一致。

这意味着您只需要替换父节点中的广播呼叫:

 MPI_Bcast( (void*)msg_send, 1024, MPI_CHAR, MPI_ROOT, intercomm); 

其他一些错误:

  • 对参数数量的检查应该是argc > 1
  • MPI_Comm_size(intercomm, &size)将返回1 。 您将要使用MPI_Comm_remote_size(intercomm, &size)

如果您在生成子进程后不想处理内部通信器,则可以使用MPI_Intercomm_merge从您的intercommunicator创建一个内部通信器。 基本上,它看起来像这样:

产卵:

 MPI_Comm_spawn( argv[0], MPI_ARGV_NULL, np, MPI_INFO_NULL, 0, MPI_COMM_SELF, &intercomm, MPI_ERRCODES_IGNORE ); MPI_Intercomm_merge(intercomm, 0, &intracomm); 

Spawnee:

 MPI_Intercomm_merge(parentcomm, 1, &intracomm); 

之后,您可以继续使用intracomm (或任何您想要调用的内容),就像它是一个普通的内部通信器一样。 在这种情况下,产生过程将具有低阶排名,新过程将具有更高的排名,但您也可以使用第二个参数对其进行修改。

诸如Bcast()类的集体通信呼叫需要一个内部通信器:您正在尝试使用内部通信器( intercommparentcomm )。 您必须使用组创建方法来定义包含父进程和所有子进程的组,然后在该组上创建新的内部通信器。