Implementing MPI_Allreduce in C - why does my code hang indefinitely?

Viewed 107

I am trying to implement my own version of MPI_Allreduce in C. The logic is that odd ranks send their data to even ranks to their rank-1, ie rank 1 sends to rank 0. Rank 0 then receives the data from rank 1 and operates on it depending on the MPI_Op operator passed as an argument. I am unsure if my way of operating on the data is correct, for example if MPI_SUM is passed then for each count passed my code does recvbuf[count] += sendbuf[count]. Once the even rank has received data from the odd rank+1, it then does rank /= 2 and the contents of the while loop repeat, with rank 0, being unchanged, rank 2 becoming rank 1 and now containing the original ranks 2+3 data, and so on. Num is also halfed each interation of the while loop until it becomes 1, which is when only rank 0 should remain.

My code thus far is below:

int tree_reduction(const int rank_in, const int np, const int *sendbuf, int *recvbuf, 
                  int count, MPI_Op op, MPI_Comm comm){

  // Create variables for rank and size
  int rank = rank_in;
  int num = np;
  int tag = 0;
  int depth = 1;  // Depth of the tree

// While size is greater than 1 there is 2 or more ranks to operate on
while(num > 1){
  if(rank < num){
    if( (rank % 2) != 0 ){ // If rank is odd
      MPI_Ssend(sendbuf, count, MPI_INT, (rank-1)*depth, tag, comm);
      rank *= num;  // any ranks above 0 will be filtered out
      break;
    }
    else{  // If rank is even
      MPI_Recv(recvbuf, count, MPI_INT, (rank+1)*depth, tag, comm, 
               MPI_STATUS_IGNORE);

      /*   START OF OPERATORS   */

      if(op == MPI_SUM){
        for(int c=0; c<count; c++){
          recvbuf[c] += sendbuf[c];
        }
      }

      if(op == MPI_PROD){
        for(int c=0; c<count; c++){
          recvbuf[count] *= sendbuf[count];
        }
      }

      if(op == MPI_MIN){
        for(int c=0; c<count; c++){
          if(sendbuf[count] < recvbuf[count]){
            recvbuf[count] = sendbuf[count];
          }
        }
      }

      if(op == MPI_MAX){
        for(int c=0; c<count; c++){
          if(sendbuf[count] > recvbuf[count]){
            recvbuf[count] = sendbuf[count];
          }
        }
      }

    /*   END OF OPERATORS   */

    }
    depth *= 2;
  }
  num = num/2;
}

// NEED TO BROADCAST BACK TO ALL RANKS
MPI_Bcast(recvbuf, count, MPI_INT, 0, comm);

return 0;

When I run this with more than 2 processes, it hangs indefinitely without printing anything to the terminal, why is this?

0 Answers
Related