如果我想通过MPI发送消息并同时接收消息,我该怎么办?

时间:2014-03-27 12:51:01

标签: tcp ip mpi openmpi

Backgroup:rank 0将消息发送到排名1,在排名1完成其工作后,它将消息返回到排名0

实际上我运行了一个用于发送消息的线程,另一个用于接收 rank 0 ,如下所示:

int tag = 1;
void* thread_send(void* argc)
{
   ...;
    while(1)
   {
     if(tag == 1) 
     {
        MPI_Send(...,1,TAG_SEND,...);//send something to slave
        tag = 0;
     }
   }
   ...
}

void* thread_receive(void* argc)
{
    while(1)
    {
      MPI_Recv(...,0,TAG_RECV,...); //ready for receiving from slave
      tag = 1;
    }
}

排名1 中我运行这样一个帖子:

void* slave(void* argc)
{   
    ...;
    while(1)
    {
        MPI_Probe(0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
        switch(status.MPI_TAG){
        case TAG_SEND:
        MPI_Recv(..,0,TAG_SEND,..);
        break;
        }
        MPI_Send(...,0,MPI_RECV,...); //notify rank 0 slave has done his work
    }
}

然后我收到了这样的错误:

    [comp01-mpi.gpu01.cis.k.hosei.ac.jp][[54135,1],0]
    [btl_tcp_endpoint.c:486:mca_btl_tcp_endpoint_recv_connect_ack] 
    received unexpected      process identifier [[16641,0],301989888]

实际上一台机器有几个接口,我知道这可能是个问题,所以我分配参数     --mca btl_tcp_if_include eth0 --mca oob_tcp_if_include eth0 避免网络流量。

我做错了吗?我将非常感谢你给我的任何建议,谢谢。

感谢@HristoIliev,我检查了Open MPI:

    MPI_Init_thread(&argc,&argv,MPI_THREAD_MULTIPLE,&provide_level);
    if(provide_level < MPI_THREAD_MULTIPLE){
        printf("Error: the MPI library doesn't provide the required thread level\n");
        MPI_Abort(MPI_COMM_WORLD,0);
    }

我得到了错误:

Error: the MPI library doesn't provide the required thread level

这意味着我不能使用多个线程,那么我还能做什么呢?

现在我使用的是非blocing发送(Isend)和接收(Irecv),代码是这样的: 发送帖子:

int tag = 1;
    void* thread_send(void* argc)
{

   ...;
    while(1)
   {
     while(1)
     {
          MPI_Irecv(&tag,MPI_INT,1,MSG_TAG,MPI_COMM_WORLD,&request);
          if(tag == 1) break;
          printf("tag is %d\n",tag);
          MPI_Wait(&request,&status);
     }

        MPI_Send(...,1,MSG_SEND,...);//send something to slave
        tag = 0;

   }
   ...
}

接收主题

void* slave(void* argc)
    {   
        ...;
        while(1)
        {
            MPI_Probe(0,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
            switch(status.MPI_TAG){
            case TAG_SEND:
            MPI_Recv(..,0,MSG_Send,..);
            break;
            }
            int tag = 1;
            MPI_Isend(&tag,1,MPI_INT,0,MSG_TAG,MPI_COMM_WORLD,&request); //notify rank 0 slave has done his work
           MPI_Wait(&request,&status);
           printf("slave is idle now \n");
        }
    }

它的印刷方式如下:

tag is 0
slave is idle now

并挂在这里

1 个答案:

答案 0 :(得分:0)

我通过更改Irecv()函数的位置解决了这个问题,如下所示:

发送帖子

int tag = 1;
    void* thread_send(void* argc)
{

   ...;
    while(1)
   {
     while(1)
     {

          if(tag == 1) break;
          printf("tag is %d\n",tag);
          MPI_Irecv(&tag,MPI_INT,1,MSG_TAG,MPI_COMM_WORLD,&request);
          MPI_Wait(&request,&status);
     }

        MPI_Send(...,1,MSG_SEND,...);//send something to slave
        tag = 0;

   }
   ...
}.

总之,要同时发送和接收消息,如果您的MPI支持多线程模式,您可以使用多个线程,您可以在启动MPI程序时检查它:

MPI_Init_thread(&argc,&argv,MPI_THREAD_MULTIPLE,&provide_level);
    if(provide_level < MPI_THREAD_MULTIPLE){
        printf("Error: the MPI library doesn't provide the required thread level\n");
        MPI_Abort(MPI_COMM_WORLD,0);
    }

或者,如果您的MPI不支持多线程模式,您可以使用非阻塞通信。