可笑的简单 MPI_Send/Recv 问题我不明白

Posted

技术标签:

【中文标题】可笑的简单 MPI_Send/Recv 问题我不明白【英文标题】:Ridiculously simple MPI_Send/Recv problem I don't understand 【发布时间】:2011-07-24 17:40:06 【问题描述】:

我有两个具有不同算法的函数。在第一个函数中,我实现了非阻塞通信(MPI_Irecv、MPI_Isend)并且程序运行没有任何错误。即使我将非阻塞更改为阻塞通信,一切都很好。没有僵局。 但是,如果我用这样的基本阻塞通信实现第二个功能(将算法简化为问题):

 if( my_rank == 0)
    
      a = 3 ;
      MPI_Send(&a,1,MPI_DOUBLE,1,0,MPI_COMM_WORLD) ;
    

    else if( my_rank == 1 )
    
      MPI_Recv(&a,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD, &status ) ;
    

所以,进程 1 应该从进程 0 接收值 a。但是我收到了这个错误:

MPI_Recv 中的致命错误:消息 截断,错误堆栈: MPI_Recv(187).......................: MPI_Recv(buf=0xbfbef2a8, count=1, MPI_DOUBLE,src=0,标签=0, MPI_COMM_WORLD,状态=0xbfbef294) 失败的 MPIDI_CH3U_Request_unpack_uebuf(600): 消息被截断;收到 32 个字节 但缓冲区大小为 8 排名 2 在作业 39 布拉布拉引起集体 中止所有等级的退出状态 等级2:被信号9杀死

如果我只使用这两个函数之一来运行程序,那么它们会按预期工作。但两者一起导致上面的错误消息。我确实理解错误消息,但我不知道我能做些什么来防止它。有人可以向我解释我必须在哪里寻找错误吗?由于我没有在第一个函数中遇到死锁,因此我假设第一个函数不会有未收到的发送,这会导致第二个函数出错。

【问题讨论】:

问题不在于 Recv 与 Irecv,当然也不是任何死锁。问题是来自任务 0 的 Rank 2 的 Recv(),它接收单个 MPI_DOUBLE,正在与来自大小为 32 字节的 rank 0 的 SEND 匹配(可能是 4 个双精度数?)。因此消息被截断错误。所以我们需要查看更多代码来了解发生了什么。 我知道。第二个功能仅包含发送/接收操作。它肯定位于第一个函数中,因为(取决于用户输入)这正是通信数组的大小。但那怎么可能呢?所有发送/接收操作必须完成,否则会导致死锁。还是我完全错了?整个代码大约有六百行。必须简化它...可能需要一段时间。 【参考方案1】:

所以,这里是第一个函数:

MPI_Type_vector(m,1,m,MPI_DOUBLE, &column_mpi_t ) ;
MPI_Type_commit(&column_mpi_t) ;

T = (double**)malloc(m*sizeof(double*)) ;
T_data = (double*)malloc(m*m*sizeof(double)) ;


for(i=0;i<m;i++)

  T[i] = &(T_data[i*m]) ;


if(my_rank==0)

  s = &(T[0][0]) ;
  for(i=1;i<p;i++)
  
    MPI_Send(s,1,column_mpi_t,i,0,MPI_COMM_WORLD) ;
  

for(k=0;k<m-1;k++)

  if(k%p != my_rank)
  
    rbuffer = &(T[0][k]) ;
    MPI_Recv(rbuffer,1,column_mpi_t,k%p,0,MPI_COMM_WORLD,&status) ;
  

  for(j=k+1;j<n;j++)
  
    if(j%p==my_rank)
    
      if(j==k+1 && j!=n-1)
      
        sbuffer = &(T[0][k+1]) ;
        for(i=0;i<p;i++)
        
          if(i!= (k+1)%p )
            MPI_Send(sbuffer,1,column_mpi_t,i,0,MPI_COMM_WORLD) ;
        
               
    
  

我得出结论,派生数据类型是我的问题的根源。有人知道为什么吗?

好吧,我错了。如果我将 MPI_Irecv/send 中的 MPI 数据类型更改为 MPI_DOUBLE,这将适合第二个函数的 recv/send 数据类型......所以没有截断错误。所以,没办法……

【讨论】:

这里的mp 是什么?目前,发送和接收似乎不匹配。

以上是关于可笑的简单 MPI_Send/Recv 问题我不明白的主要内容,如果未能解决你的问题,请参考以下文章

MPI_Comm_split 与 MPI_Send / MPI_Recv 的关系

python 可笑的简单刮刀(过时)

MPI消息传递MPI_Sendrecv的用法

在 FORTRAN 90 中使用 MPI_Type_Create_Subarray

可笑的生活

Cloud Bigtable 批量突变因不明原因而失败