2013-05-17 213 views
0

我想从每个进程发送一些数据给它的邻居(按等级)。为此,我尝试使用非阻塞的发送和接收呼叫MPI_Isend/MPI_Irecv和相应的呼叫MPI_Waitall以确保在使用数据之前发生了传输。“死锁”与MPI_Waitall

下面是我想要做的

#include <mpi.h> 
#include <iostream> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    MPI_Init(&argc,&argv); 
    int rank,comm_size; 

    MPI_Comm_rank(MPI_COMM_WORLD,&rank); 
    MPI_Comm_size(MPI_COMM_WORLD,&comm_size); 

    MPI_Request reqs[4]; 

    int sbuff1[10]; 
    int sbuff2[10]; 
    int rbuff1[10]; 
    int rbuff2[10]; 

    int count = 0; 

    if(rank>0) 
    { 
     MPI_Irecv(rbuff1,10,MPI_INT,rank-1,0,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
     MPI_Isend(sbuff1,10,MPI_INT,rank-1,1,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
    } 

    if(rank<comm_size-1) 
    { 
     MPI_Irecv(rbuff2,10,MPI_INT,rank+1,2,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
     MPI_Isend(sbuff2,10,MPI_INT,rank+1,3,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
    } 

    MPI_Waitall(count,reqs,MPI_STATUS_IGNORE); 

    if(rank==0) 
      cout << "Successfully exchanged data." << endl; 

    MPI_Finalize(); 

    return 0; 
} 

一个小例子,不幸的是这代码永远不会使它通过在最后打印出来的消息。

我的问题是:数据是否正确发送,但我打电话给MPI_Waitall是某种错误?如果是的话,我需要改变什么才能使这个简单的代码运行,如果不是,还有什么是错误的?

回答

1

您设置的send/recv标签永远不会匹配。

这一点修复

#include <mpi.h> 
#include <iostream> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    MPI_Init(&argc,&argv); 
    int rank,comm_size; 

    MPI_Comm_rank(MPI_COMM_WORLD,&rank); 
    MPI_Comm_size(MPI_COMM_WORLD,&comm_size); 

    MPI_Request reqs[4]; 

    int sbuff1[10]; 
    int sbuff2[10]; 
    int rbuff1[10]; 
    int rbuff2[10]; 

    int count = 0; 

    if(rank>0) 
    { 

     MPI_Irecv(rbuff1,10,MPI_INT,rank-1,0,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
     MPI_Isend(sbuff1,10,MPI_INT,rank-1,1,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
    } 

    if(rank<comm_size-1) 
    { 
     /// changed tag 2 -> 1 
     // MPI_Irecv(rbuff2,10,MPI_INT,rank+1,2,MPI_COMM_WORLD,&reqs[count]); 
     MPI_Irecv(rbuff2,10,MPI_INT,rank+1,1,MPI_COMM_WORLD,&reqs[count]); 
     count++; 

     /// changed tag 3 -> 0 
     // MPI_Isend(sbuff2,10,MPI_INT,rank+1,3,MPI_COMM_WORLD,&reqs[count]); 
     MPI_Isend(sbuff2,10,MPI_INT,rank+1,0,MPI_COMM_WORLD,&reqs[count]); 
     count++; 
    } 

    MPI_Waitall(count,reqs,MPI_STATUS_IGNORE); 

    if(rank==0) 
      cout << "Successfully exchanged data." << endl; 

    MPI_Finalize(); 

    return 0; 
} 

使得它的工作

$> mpirun -n 5 ./testling 
Successfully exchanged data. 

跑x86_84的Linux与MPICH2 V1.5(九头蛇)

+0

卫生署!我确实尝试了不同的标签,但我想我没有选择正确的组合。我从来没有真正理解标签的用途。我已经编写了程序,之后在每次MPI调用后任意递增标签,并且这样工作正常吗? – Dan

+0

如果对话框是同步的,并且正确地递增标签,那么没有预期的危害。顺便说一句 - 我不想打扰太多,但我认为你会用((rank + 1)%comm_size)分支逻辑做得更好。 – Solkar

+0

我不需要在第一个和最后一个流程之间进行转换,因此它可以,但谢谢。 – Dan