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

时间:2012-04-02 03:01:20

标签: c mpi

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

#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。

3 个答案:

答案 0 :(得分:3)

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

  

如果comm是一个intercommunicator,那么该调用涉及intercommunicator中的所有进程,但是有一个组(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)代替。

答案 1 :(得分:2)

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

产卵:

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(或任何您想要的名称),就像它是一个普通的内部通信器一样。在这种情况下,产生过程将具有低阶排名,新过程将具有更高的排名,但您也可以使用第二个参数修改它。

答案 2 :(得分:-1)

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