Python 3.x MPI4PY:与邻居的环网通信

Python 3.x MPI4PY:与邻居的环网通信,python-3.x,mpi,mpi4py,Python 3.x,Mpi,Mpi4py,请帮忙 我在python中使用MPI(=消息传递接口)进行环形通信,这意味着每个列组都在互相发送和接收消息。我知道实现这一点的一种方法是使用例如MPI.COMM\u WORLD.issend()和MPI.COMM\u WORLD.recv(),这是可行的 现在我想通过使用MPI.Topocomm.Neighbor\u alltoall以不同的方式实现相同的输出,但这不起作用。我编写了一个C代码并在那里工作,因此可以使用此函数获得相同的输出,但当我用python实现此功能时,它不起作用。请在下面找

请帮忙

我在python中使用MPI(=消息传递接口)进行环形通信,这意味着每个列组都在互相发送和接收消息。我知道实现这一点的一种方法是使用例如
MPI.COMM\u WORLD.issend()
MPI.COMM\u WORLD.recv()
,这是可行的

现在我想通过使用
MPI.Topocomm.Neighbor\u alltoall
以不同的方式实现相同的输出,但这不起作用。我编写了一个C代码并在那里工作,因此可以使用此函数获得相同的输出,但当我用python实现此功能时,它不起作用。请在下面找到C代码和Python代码

函数的定义是(Python的mpi4py包):

邻居(所有人) 拓扑通信邻居(自身、发送BUF、接收VBUF)

我不明白以下几点:

  • 为什么
    recbuf
    不是返回值?这似乎是一个争论
  • 如何在Python中实现环通信
  • 感谢您的时间和支持

    我的工作C代码:

    
    #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();
    }
    

    请发布您的工作
    C
    代码和您在Python中的尝试。@GillesGouaillardet我发布了这两个代码,也许您可以帮助我:)您希望
    mpi4py
    会猜出您显式传递到
    C
    中的位移吗?
    *v
    (向量)和
    *w
    (广义)中的接收缓冲区mpi4py调用是一个输入参数,它是多个对象的列表或元组,其中只有一个是(输出)接收缓冲区。对于
    *v
    版本,您需要提供从每个列组接收的元素数量以及放置它们的位移。对于
    *w
    版本,还需要指定MPI数据类型。有关如何使用
    邻居\u all toall()
    ,请参阅。
    
    #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();
    }
    
    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)