MPI4PY: ring communication with neighbor_alltoallw

472 Views Asked by At

Please Help!

I am using MPI (= Message Passing Interface) in python for a ring communication, which means that every rank are sending and receiving from each other. I know one way to realize this is by using for instance MPI.COMM_WORLD.issend()and MPI.COMM_WORLD.recv(), this is working and done.

Now I want to realize the same Output on a different way by using MPI.Topocomm.Neighbor_alltoallw but this is not working. I wrote a C Code and is working there, so the same output can be reached with this function, but when I implement this in python it is not working. Please find below the C Code and the Python Code

The definition of the Function says (mpi4py Package for Python):

Neighbor_alltoallw(...) Topocomm.Neighbor_alltoallw(self, sendbuf, recvbuf)

Neighbor All-to-All Generalized

I do not understand following things:

  1. why is recbuf not a return value? it seems to be an argument here
  2. how can this be implmented for a ring communication in Python?

Thank you for your time and support!

my working C Code:


#include <stdio.h>
#include <mpi.h>

#define to_right 201
#define max_dims 1 


int main (int argc, char *argv[])
{
  int my_rank, size;
  int snd_buf, rcv_buf;
  int right, left;
  int sum, i;

  MPI_Comm    new_comm;
  int         dims[max_dims],
              periods[max_dims],
              reorder;

  MPI_Aint    snd_displs[2], rcv_displs[2];
  int         snd_counts[2], rcv_counts[2]; 
  MPI_Datatype snd_types[2], rcv_types[2]; 

  MPI_Status  status;
  MPI_Request request;


  MPI_Init(&argc, &argv);

  /* Get process info. */
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  /* Set cartesian topology. */
  dims[0] = size;
  periods[0] = 1;
  reorder = 1;
 
  MPI_Cart_create(MPI_COMM_WORLD, max_dims, dims, periods,
                  reorder,&new_comm);

  /* Get coords */
  MPI_Comm_rank(new_comm, &my_rank);
  /* MPI_Cart_coords(new_comm, my_rank, max_dims, my_coords); */ 

  /* Get nearest neighbour rank. */
  MPI_Cart_shift(new_comm, 0, 1, &left, &right);

  /* Compute global sum. */
 
  sum = 0;
  snd_buf = my_rank;
  rcv_buf = -1000; /* unused value, should be overwritten by first MPI_Recv; only for test purpose */

  rcv_counts[0] = 1;  MPI_Get_address(&rcv_buf, &rcv_displs[0]); snd_types[0] = MPI_INT;
  rcv_counts[1] = 0;  rcv_displs[1] = 0 /*unused*/;              snd_types[1] = MPI_INT;
  snd_counts[0] = 0;  snd_displs[0] = 0 /*unused*/;              rcv_types[0] = MPI_INT;
  snd_counts[1] = 1;  MPI_Get_address(&snd_buf, &snd_displs[1]); rcv_types[1] = MPI_INT;

  for( i = 0; i < size; i++) 
  {
    /* Substituted by MPI_Neighbor_alltoallw() :
    MPI_Issend(&snd_buf, 1, MPI_INT, right, to_right,
                                new_comm, &request);
    MPI_Recv(&rcv_buf, 1, MPI_INT, left, to_right,
                              new_comm, &status);
    MPI_Wait(&request, &status);
    */    

    MPI_Neighbor_alltoallw(MPI_BOTTOM, snd_counts, snd_displs, snd_types, 
                           MPI_BOTTOM, rcv_counts, rcv_displs, rcv_types, new_comm);

    snd_buf = rcv_buf;
    sum += rcv_buf;
  }

  printf ("PE%i:\tSum = %i\n", my_rank, sum);

  MPI_Finalize();
}

My not working Python Code:

from mpi4py import MPI

size = MPI.COMM_WORLD.Get_size()
my_rank = MPI.COMM_WORLD.Get_rank()
to_right =201
max_dims=1

dims = [max_dims]
periods=[max_dims]
dims[0]=size
periods[0]=1
reorder = True

new_comm=MPI.Intracomm.Create_cart(MPI.COMM_WORLD,dims,periods,True)
my_rank= new_comm.Get_rank()
left_right= MPI.Cartcomm.Shift(new_comm,0,1)

left=left_right[0]
right=left_right[1]

sum=0
snd_buf=my_rank
rcv_buf=-1000 #unused value, should be overwritten, only for test purpose

for counter in range(0,size):
    MPI.Topocomm.Neighbor_alltoallw(new_comm,snd_buf,rcv_buf)
    snd_buf=rcv_buf
    sum=sum+rcv_buf

print('PE ', my_rank,'sum=',sum)
0

There are 0 best solutions below