【问题标题】:MPI_Send and MPI_Recv not matching CMPI_Send 和 MPI_Recv 不匹配 C
【发布时间】:2015-05-14 07:41:00
【问题描述】:

我正在尝试在这里实现一个工作池。我应该总共向从属进程发送 100 个不同的数字。然后每个从属进程返回一些东西给主进程,另一个不同的数字由主进程发送给从属进程。这种情况一直持续到所有 100 次迭代结束。

我的程序陷入了无限循环,我认为这是由于 MPI_Send 和 MPI_Recv 的映射不正确。我无法弄清楚我做错了什么。我花了好几个小时研究这个但无济于事。我是 MPI 和一般编程的新手。代码如下:

if(rank == 0) {
        int i,iteration = 0, a=0,inside=0,temp=0;
        for(i = 1; i < slaves; i++) {
        MPI_Send(&iteration,1,MPI_INT,i,0,MPI_COMM_WORLD);
        MPI_Send(&a,1,MPI_INT,i,1,MPI_COMM_WORLD);
        iteration++;
    }
    while(iteration < 100+slaves){
        MPI_Recv(&temp,1,MPI_INT,MPI_ANY_SOURCE,0, MPI_COMM_WORLD, &status);
        if(iteration < 100) {
            MPI_Send(&iteration,1,MPI_INT,status.MPI_SOURCE,0,MPI_COMM_WORLD);
            MPI_Send(&a,1,MPI_INT,status.MPI_SOURCE,1,MPI_COMM_WORLD);
        }
        iteration++;
        inside = inside + temp;
    }
}
else {
    int iteration=0,count=0;
    if(iteration < 100) {
        MPI_Recv(&iteration,1,MPI_INT,0,0,MPI_COMM_WORLD,&status);
        MPI_Recv(&count,1,MPI_INT,0,1,MPI_COMM_WORLD,&status);
        MPI_Send(&count,1,MPI_INT,0,0,MPI_COMM_WORLD);
    }
}

【问题讨论】:

  • 为什么 for 循环从 1 开始而不是从 0 开始:for(i = 1; i &lt; slaves; i++) {?
  • @AntoJurković 因为master(rank=0)只应该向slave(rank>0)发送数据。

标签: c mpi


【解决方案1】:

你也需要在你的奴隶队伍中循环。就目前而言,您将iterationa 从主服务器发送到从服务器,将count 从从服务器发送回主服务器,然后主服务器尝试从一个内部发送iterationa while 循环,而奴隶们愉快地退出了else 块并继续他们快乐的方式。要么去掉主进程中的while 循环,这样它就不会发送从属进程永远不会收到的东西,或者在从属进程中添加一个循环,以便它们能够正确接收该数据。

【讨论】:

    【解决方案2】:

    在 MPI 中最重要的事情之一是理解,通常每个单独的进程都执行相同的程序。这使mpi_rank 成为您最好的朋友之一,因为您需要它来区分每个进程必须完成的不同任务。

    另一个需要理解的重点是 MPI 中的阻塞/非阻塞通信是如何工作的。这里我们使用阻塞通信(MPI_Send()MPI_Recv())。这意味着一个进程将在像MPI_Recv() 这样的函数调用处停止,并等到通信伙伴到达它的“对方”(MPI_Send(),向我发送一些东西)。

    您的程序卡住的事实很好地表明了没有相同数量的MPI_Send()MPI_Recv() 调用:某个进程仍在等待接收消息/能够发送消息。

    对于你的例子,我会尝试做这样的事情:

    while( iterations < 100 ){
      // in general every process has to do something for 100 times,
      // but we have to have to distinguish between master and slaves.
    
      if( mpi_rank == 0 ){
        // The master process...
        for( int slave_rank = 1; slave_rank < mpi_size; slave_rank++ ){
          // ... has to send, receive and send once again something to/from every(!) slave, ...
          MPI_Send( [one int to slave_rank] );
          MPI_Recv( [one int from slave_rank] );
          MPI_Send( [another int to slave_rank] );
        }
      }
      else{
        //... while the slaves just have to receive, send and receive again from/to one process (the master)
        MPI_Recv( [one int from master] );
        MPI_Send( [one int to master] );
        MPI_Recv( [another int from master] );
      }
      iterations++;
    }
    

    您的任务听起来像:Master 将 int 发送到 slave #1、#2、#3.....,然后他从 #1、#2、#3.... 接收,然后他发送另一个 int 到#1,#2,#3。您可能会意识到您必须循环遍历所有从属队列 3 次。

    这个解决方案是不同的(虽然结果是一样的),但是更短:Master 发送 int 给 slave #1,然后从 slave #1 接收 int,然后发送另一个 int 给 slave #1。之后,对从站 #2、#3、#4 重复相同的操作......这样我们只需遍历所有从站排名一次。

    【讨论】:

      猜你喜欢
      • 2011-11-11
      • 2014-04-17
      • 2011-01-24
      • 2017-10-25
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 2018-09-11
      • 1970-01-01
      相关资源
      最近更新 更多