【问题标题】:Why is this MPI program stalling为什么这个 MPI 程序停滞不前
【发布时间】:2013-07-05 09:34:17
【问题描述】:
//#define SIZE 3
void master(int n,int size)
{
for(int j=1;j<size;j++){
    MPI_Send(&n,1,MPI_INT,j,1,MPI_COMM_WORLD);
    printf("\n Sent %d to process %d",n,j);
    fflush(stdout);
    }
}

void slave(int size)
{
for(int j=1;j<size;j++){
    int k=0;
    MPI_Status status;
    MPI_Recv(&k,1,MPI_INT,0,1,MPI_COMM_WORLD,&status);
    printf("\n Process %d has received %d",j,k);
    fflush(stdout);
    }
}

int main(int argc,char** argv)
{

MPI_Init(&argc,&argv);
int la_size;
int rank;
MPI_Comm_size(MPI_COMM_WORLD,&la_size);

MPI_Comm_rank(MPI_COMM_WORLD,&rank);

for(int i=0;i<3;i++){
    if(rank==0)
        master(i,la_size);
    else
        slave(la_size);

}
MPI_Finalize();
printf("\nprogram finished...");
fflush(stdout);
return 0;

}  

上面的程序看起来很简单,但它停滞不前。是死锁吗? 输出是:

     Sent 0 to process 1  
 Sent 0 to process 2  
 Sent 1 to process 1  
 Sent 1 to process 2  
 Process 1 has received 0  
 Process 2 has received 1  
 Process 1 has received 2  
 Sent 2 to process 1  
 Sent 2 to process 2  
 Process 1 has received 0  
 Process 2 has received 1  
 Process 1 has received 2

【问题讨论】:

  • 为什么每个人都发布他们的代码并期望人们调试?
  • 因为我们不明白发生了什么......事情是如何运作的。有没有更好的方法来问这些问题?

标签: c mpi


【解决方案1】:

main 中循环的每次迭代中,rank 0 对多个从属 rank 中的每一个进行一次发送,但每个从属发布的接收数量与从属 rank 的总数一样多。由于没有发布的发送来匹配后来的接收,接收者无限期地阻塞,程序挂起。

【讨论】:

  • 是的,我也认为这可能是问题所在。但是我还能如何重新组织代码?我想将代码保留在函数中
  • 这与功能无关。在外循环的每次运行中,master 只与每个 slave 交互一次,但每个 slave 尝试与 master 交互多次。看看你的循环结构。
  • 所以我想我应该摆脱从站中的 for 循环。
  • 哦,还有,您在slave 中的打印谎言-循环索引不是进程等级。
  • 所以基本上,整个 main() 是在三个不同的进程上执行的......我没有清楚地掌握这一点
【解决方案2】:

感谢Novelocrat的回答,正确的代码其实是这样的:

#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>
//#define SIZE 3

void master(int n,int size)
{
    for(int j=1;j<size;j++){
    MPI_Send(&n,1,MPI_INT,j,1,MPI_COMM_WORLD);
    printf("\n Sent %d to process %d",n,j);
    fflush(stdout);
    }
}

void slave(int size)
{
    int k=0,rank=0;
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Status status;
    MPI_Recv(&k,1,MPI_INT,0,1,MPI_COMM_WORLD,&status);
    printf("\n Process %d has received %d",rank,k);
    fflush(stdout);

}

int main(int argc,char** argv)
{

    MPI_Init(&argc,&argv);
    int la_size;
    int rank;
    MPI_Comm_size(MPI_COMM_WORLD,&la_size);

    MPI_Comm_rank(MPI_COMM_WORLD,&rank);

    for(int i=0;i<3;i++){
    if(rank==0)
        master(i,la_size);
    else
        slave(la_size);

    }
    MPI_Finalize();
    printf("\nprogram finished...");
    fflush(stdout);
    return 0;

}

【讨论】:

  • 另外,如果你真的要向所有从属队列发送单个值n,你应该将其表述为MPI_Bcast,而不是循环MPI_Send
  • 是的。我目前只是在编写玩具程序来帮助我掌握 MPI。
  • Linux 上是否有任何调试环境可以发送任何有用的信息?我目前只是在这里使用终端。如果程序挂起,我不知道为什么会这样。
  • 人们似乎使用的标准工具是商业调试器 Alinea DDT。我想不出一个通用的免费软件工具,但 DDT 可能是免费供个人使用的。
猜你喜欢
  • 2016-05-13
  • 2011-11-24
  • 1970-01-01
  • 2013-05-08
  • 1970-01-01
  • 2021-11-07
  • 2012-09-21
  • 2013-07-07
  • 2020-01-28
相关资源
最近更新 更多