none
attempting to send a message to the local process without a prior matching receive RRS feed

  • Question

  • Hallo,

    I am new to MPI programming, there are errors in my code as follows:

    [0] fatal error
    Fatal error in MPI_Send: Other MPI error, error stack:
    MPI_Send(buf=0x00000000016E7BA0, count=16, MPI_FLOAT, dest=0, tag=0, MPI_COMM_WORLD) failed
    DEADLOCK: attempting to send a message to the local process without a prior matching receive

    And my code is as follows:

    #include<stdio.h>
    #include<malloc.h>
    #include <iostream>
    #include "mpi.h"
    #define A(x,y) A[x*P+y]
    #define B(x,y) B[x*N+y]
    #define C(x,y) C[x*N+y]
    #define a(x,y) a[x*P+y]
    #define b(x,y) b[x*n+y]
    #define buffer(x,y) buffer[x*n+y]
    #define c(l,x,y) c[x*N+y+l*n]
    #define ints sizeof(int)
    #define floats sizeof(float)
    #define chars sizeof(char)
    float *a,*b,*c,*buffer;
    int s;
    float *A,*B,*C;/* A[M,P],B[K,N].正确的情况下P应该等于K,否则无法进行矩阵相乘*/
    int M,P,K,N;
    int m,n;
    int id;/*处理器编号*/
    int p; /*处理器总数*/
    FILE *dF; //用于读取输入文件内容和将计算结果输出到结果文件的临时文件指针
    MPI_Status status;
    double t1;
    double st,et;
    void READDATA()
    {
        int i,j;
        st = MPI_Wtime();
        dF=fopen("dataIn.txt","r");
        fscanf(dF,"%d%d", &M, &P);
        A=(float *)malloc(floats*M*P);
        for(i = 0; i < M; i++)
           {
               for(j=0;j <P;j++)
                  {
                      fscanf(dF,"%f",A+i*P+j);
                  }
           }
        fscanf(dF,"%d%d", &K, &N);/* 读取矩阵 B 的行,列数 K,N */
        if(K!=P)/* P必须等于K,否则矩阵A和B无法相乘*/
          {
              printf("the input is wrong\n");
          }
        B=(float *)malloc(floats*K*N);/* 是矩阵 B 分配空间 */
        for(i = 0; i < K; i++)
            for(j =0;j <N;j++)
               {
                   fscanf(dF,"%f", B+i*N+j);
               }
        fclose(dF);
        printf("Input of file \"dataln.txt\"\n");
        printf("%d\t %d\n",M,P);/* 输出矩阵 A 的维数 */
        for(i=0;i<M;i++)/*输出矩阵A的数据*/
           {
               for(j=0;j<P;j++)
                printf("%f\t",A(i,j));
               printf("\n");
           }
        printf("%d\t %d\n",K, N);/* 输出 B 矩阵的维数 */
        for(i=0;i<K;i++)/*输出B矩阵的数据*/
           {
               for(j=0;j<N;j++)
                printf("%f\t",B(i,j));
               printf("\n");
           }
        C=(float *)malloc(floats*M*N);/* 为矩阵 C 分配空间 */
    }
    int GYZ(int N,int M,int group_size)
    {
     int i;
     for(i=N; i>0; i--)
     {
      if((N%i==0)&&(M%i==0)&&(i<=group_size))
      return i;
     }
     return 1;
    }
    void OUTPUTRESULT()
    {
     int i,j;
     printf("\nOutput of Matrix C = AB\n");
     for(i=0;i<M;i++)/*输出C矩阵的结果*/
     {
      for(j=0;j<N;j++)
       printf("%f\t",C(i,j));
      printf("\n");
     }
     et=MPI_Wtime();
     printf("\n");
     printf("all time = %f seconds\n",et-st);
     printf("data distribute time = %f seconds\n",t1-st);
     printf("parallel time = %f seconds\n",et-t1);
    }
    int main(int argc, char **argv)
    {
     int i,j,k,l,size,mpl,mml ;
     MPI_Init(&argc, &argv);
     MPI_Comm_size(MPI_COMM_WORLD,&size);
     MPI_Comm_rank(MPI_COMM_WORLD,&id);
     p=GYZ(N,M,size);
     if(id==0)
     {
      READDATA();
     }
     if(id==0)/*由编号是0的进程将A,B两矩阵的行列维数M,P,K,N发送给所有其他进程*/
      for(i=1;i<p;i++)
      {
       MPI_Send(&M,1,MPI_INT,i,i,MPI_COMM_WORLD);
       MPI_Send(&P,1,MPI_INT,i,i,MPI_COMM_WORLD);
       MPI_Send(&K,1,MPI_INT,i,i,MPI_COMM_WORLD);
       MPI_Send(&N,1,MPI_INT,i,i,MPI_COMM_WORLD);
      }
     else/*编号不是0的进程接收A,B两矩阵的行列维数M,P,K,,N */
     {
      MPI_Recv(&M,1,MPI_INT,0,id,MPI_COMM_WORLD,&status);
      MPI_Recv(&P,1,MPI_INT,0,id,MPI_COMM_WORLD,&status);
      MPI_Recv(&K,1,MPI_INT,0,id,MPI_COMM_WORLD,&status);
      MPI_Recv(&N,l,MPI_INT,0,id,MPI_COMM_WORLD,&status);
     }
     m=N/p;/* m代表将矩阵按行分块后每块的行数*/
     n=M/p;/* m代表将矩阵按列分块后每块的列数*/
        if(id<p)
     {
      a=(float *)malloc(floats*m*P);/* a[m,P]用来保存本处理器拥有的矩阵A的行块*/
      b=(float *)malloc(floats*P*n);/* b[P,n|用来保存本处理器拥有的矩阵B的列子块*/
      c=(float *)malloc(floats*m*N);/* c[m,N]用来保存本处理器计算 p-1 次得到所有结果*/
      if(id%2!=0)/*为奇数号处理器分配缓冲空间*/
       buffer=(float *)malloc(K*n*floats);
      if(a==NULL||b==NULL||c==NULL)/* 如果分配空间出错,则打印出错信息*/
       printf("Allocate space fail!");
      if (id==0)/*编号是0的处理器将矩阵A,B的元素读入自己的a,b中*/
      {
       for(i=0;i<m;i++)
        for(j=0;j<K;j++)
         a(i,j)=A(i,j);
       for(i=0;i<K;i++)
        for(j=0;j<n;j++)
         b(i,j)=B(i,j);
      }
      if(id==0)/*编号是0的处理器将其他处理器的初始数据分别发送各处理器*/
      {
       for (i=1;i<p;i++)
       {
        MPI_Send(&A(m*i,0),K*m,MPI_FLOAT,i,i,MPI_COMM_WORLD);
        for(j=0;j<K;j++)
         MPI_Send(&B(i,n*i),n,MPI_FLOAT,i,i,MPI_COMM_WORLD);
       }
        free(A);
        free(B);/*释放A.B所占空间*/
      }
      else/*编号不是0的处理器从编号为0处理器接受各自的初始矩阵数据*/
      {
       MPI_Recv(a,K*m,MPI_FLOAT,0,id,MPI_COMM_WORLD,&status);
       for(j=0;j<K;j++)
        MPI_Recv(&b(j,0),n,MPI_FLOAT, 0,id,MPI_COMM_WORLD,&status);
      }
      if (id==0)
       t1=MPI_Wtime();/*编号是0的处理器记录开始矩阵相乘计算的时间*/
      for (i=0;i<p;i++)
      {
       l=(i+id)%p;
       for (k=0;k<m;k++)
        for (j=0;j<n;j++)
         for (c(l,k,j)=0,s=0;s<K;s++)
          c(l,k,j)+=a(k,s)*b(s,j);
       mml=(p+id-1 )%p;/*计算前一个进程的编号*/
       mpl=(id+l)%p;/*计算后一个进程的编号*/ 
       if (i!=p-l)
       {
        if(id%2==0)/*偶数号处理器先发送后接收*/
        {
         MPI_Send(b,K*n,MPI_FLOAT,mml,mml,MPI_COMM_WORLD);
         MPI_Recv(b,K*n,MPI_FLOAT,mpl,id,MPI_COMM_WORLD,&status);
        }
        else/*奇数号处理器先将B的列子块存于缓冲区buffer中,然后接收编号在其后面的偶数号处理器所发送的B的列子块,最后再将缓冲区中原矩阵B的列子块发送给编号在其前面的偶数号处理器*/
        {
         for(k=0;k<K;k++)
          for(j=0;j<n;j++)
           buffer(k,j)=b(k,j);
         MPI_Recv(b,K*n,MPI_FLOAT,mpl,id,MPI_COMM_WORLD,&status);
         MPI_Send(buffer,K*n,MPI_FLOAT, mml,mml,MPI_COMM_WORLD);
        }
       }
      }
      if (id==0)/*编号是0的进程直接将计算结果保存到结果C矩阵中*/
       for(i=0;i<m;i++)
        for(j=0;j<N;j++)
         C(i,j)=*(c+i*N+j);
      if(id!=0)/*编号不是0的进程则要把计算结果发送到编号是0的处理器中去*/
       MPI_Send(c,m*N,MPI_FLOAT,0,id,MPI_COMM_WORLD);
      else/*编号是0的进程负责接收其他进程的计算结果并保存到结果C矩阵中*/
      {
       for(k=l;k<p;k++)
       {
        MPI_Recv(c,m*N,MPI_FLOAT,k,k,MPI_COMM_WORLD,&status);
        for(i=0;i<m;i++)
         for(j=0;j<N;j++)
          C((k*m+i),j)=*(c+i*N+j);
       }
      }
      if(id==0) /* 0号处理器负责将A,B,C矩阵打印输出给用户,并输出用于分发数据和并行计算的时间*/
       OUTPUTRESULT();
     }
     MPI_Finalize();
     if(id<p)/*释放临时分配空间*/
     {
      free(a);
      free(b);
      free(c);
      if(id==0) /*如果是编号为0号进程要释放C矩阵*/
       free(C);
      if(id%2!=0) /*如果是奇数号进程要释放buffer */
       free(buffer);
     }
     return (0);
    }

    Saturday, April 1, 2017 11:29 AM

All replies

  • Hi,

    The error message means that a process is attempting to send to itself without a matching receive. In this case I believe rank 0 is sending a message to rank 0 itself.

    The code is too long and hard for me to understand what's going on there. You could try to reduce the program to some smaller block of codes to better isolate the problem. My guess is that the error happens somewhere within this code block. Is it possible that mml is 0?

    if (i!=p-l)
       {
        if(id%2==0)/*偶数号处理器先发送后接收*/
        {
         MPI_Send(b,K*n,MPI_FLOAT,mml,mml,MPI_COMM_WORLD);
         MPI_Recv(b,K*n,MPI_FLOAT,mpl,id,MPI_COMM_WORLD,&status);
        }
        else/*奇数号处理器先将B的列子块存于缓冲区buffer中,然后接收编号在其后面的偶数号处理器所发送的B的列子块,最后再将缓冲区中原矩阵B的列子块发送给编号在其前面的偶数号处理器*/
        {
         for(k=0;k<K;k++)
          for(j=0;j<n;j++)
           buffer(k,j)=b(k,j);
         MPI_Recv(b,K*n,MPI_FLOAT,mpl,id,MPI_COMM_WORLD,&status);
         MPI_Send(buffer,K*n,MPI_FLOAT, mml,mml,MPI_COMM_WORLD);
        }
       }

    Wednesday, April 5, 2017 3:14 PM