首页 > 解决方案 > MPI4PY:与neighbor_alltoallw 进行环形通信

问题描述

请帮忙!

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

现在我想通过使用以不同的方式实现相同的输出,MPI.Topocomm.Neighbor_alltoallw但这不起作用。我写了一个 C 代码并在那里工作,所以这个函数可以达到相同的输出,但是当我在 python 中实现它时它不起作用。请在下面找到 C 代码和 Python 代码

函数的定义说(mpi4py Package for Python):

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

Neighbor All-to-All Generalized

我不明白以下事情:

  1. 为什么 recbuf不是返回值?这似乎是一个论点
  2. 如何在 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();
}

我不工作的 Python 代码:

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)

标签: python-3.xmpimpi4py

解决方案


推荐阅读