2012-04-02 48 views
8

(初学者问题)我试图用MPI_Comm_Spawn动态生成进程,然后向子进程广播一条消息,但程序停止在从根进程到广播这些孩子。我正在关注来自http://www.mpi-forum.org/docs/docs.html的文档,但我无法使其工作。有人可以帮我吗?MPI Spawn:根进程不与子进程通信

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

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。

回答

-1

集体通信电话如Bcast()需要一个intracommunicator:你正在尝试使用互通器(intercommparentcomm)。您必须使用组创建方法来定义包含父进程和所有子进程的组,然后在该组中创建一个新的intracommunicator。

+0

这并不准确,因为@ bfroehle指出。您可以与对讲机进行集体呼叫。你只需要小心并阅读单独的规范。 – 2013-08-21 13:16:47

3

正如@suszterpatt指出的,你正在使用“Intercommunicator”(而不是“Intracommunicator”)。知道了这一点,看着MPI_Bcast,我们看到:

如果通讯是一个intercommunicator,则调用涉及到intercommunicator所有进程,但有一个组(A组),其定义根进程。另一组(组B)中的所有进程都在参数根中传递相同的值,这是根组A中的根的等级。根以root身份传递值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)
2

如果您在产生子流程后不想处理intercommunicator,则可以使用MPI_Intercomm_merge从您的intercommunicator创建intracommunicator。从本质上讲,它应该是这样的:

产卵:

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(或任何你想将它命名),就好像它是一个普通的intracommunicator。在这种情况下,产卵过程将具有较低的等级,新的过程将具有较高的等级,但您可以使用第二个参数对其进行修改。

+0

这项工作到底如何?我刚刚发布了一个相关的[问题](http:// stackoverflow。com/questions/20755060/can-a-spawned-process-communicate-with-the-main-mpi-communicator),这个合并声明可能会起作用,但我对“inter”,“intra”不同部分感到困惑码。 – user989762 2013-12-24 05:05:18