【问题标题】:MPI_Cart_Shift.Corner NeighborhoodMPI_Cart_Shift.Corner 邻里
【发布时间】:2016-03-15 09:35:09
【问题描述】:

我需要创建一个具有立方体拓扑的通信器,然后选择立方体的面,使用 MPI_Cart_Shift 在处于边缘的进程之间实现消息传递。例如,我是等级为 0(R0)的进程,我的邻域是 R2、R4、R6(立方体的下表面)。我可以找到 R2 和 R4,但我不明白如何找到 R6。我的代码:

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

int main(int argc, char *argv[])
{
int rank, k;
int size; 
int ndims = 3; 
int source, dest;
int up,down,right,left,up3, down3;

int edges[6][4] = {{0,1,5,4},
                {4,5,7,6},
                {2,3,1,0},
                {6,7,3,2},
                {1,3,7,5},
                {0,2,6,7}};

int t, incep=0;
char processor_name[MPI_MAX_PROCESSOR_NAME];

MPI_Comm comm, comm3d;
int dims[3]={0,0,0}, coords[3]={0,0,0},
    periods[3]={1,1,1}, reorder = 0;


MPI_Status status;


int user_edge;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Dims_create(size, ndims, dims);


  MPI_Cart_create(MPI_COMM_WORLD, ndims, dims, periods, reorder, &comm);


  MPI_Cart_coords(comm, rank, 3, coords);

 fflush(stdout);
     printf("Rank %d coordinates are %d %d %d\n", rank, coords[0], coords[1], coords[2]);
 MPI_Barrier(comm);

    int leftrank, rightrank;
    int downrank, uprank;

MPI_Comm_rank(comm, &rank);
    MPI_Cart_coords(comm, rank, 2, coords);
MPI_Cart_shift(comm, 0, -1, &downrank, &uprank); 
MPI_Sendrecv(buffer, 10, MPI_INT, downrank, 123, buffer2, 10, MPI_INT, uprank, 123, comm, &status);
MPI_Cart_shift(comm, 1, -1, &rightrank, &leftrank); 
    MPI_Sendrecv(buffer, 10, MPI_INT, leftrank, 123, buffer2, 10, MPI_INT, rightrank, 123, comm, &status);


printf("P:%d My neighbors are rightRank: %d downRank:%d leftRank:%d upRank:%d diagonal:%d diagonalX:%d\n", rank,rightrank,downrank,leftrank,uprank,diagonal,diagonalX);



MPI_Finalize();

return 0;

}

我会尝试添加类似这样的内容 MPI_Cart_shift(comm, 2, 1, &diagonal, &diagonalX);但是对于 R0,它向我展示了 R1,我明白了.... 我怎样才能获得角落社区?

【问题讨论】:

    标签: c++ mpi topology cartesian


    【解决方案1】:

    您可以使用 MPI_Cart_rank 来查找您需要的信息。

    int MPI_Cart_rank(MPI_Comm comm, const int coords[], int *rank)
    

    这里comm是一个笛卡尔拓扑的通信器。 coords 是一个整数数组(该数组的大小是笛卡尔拓扑的维数),其中包含进程的坐标(在您的情况下,R6 为 1,1,0)。然后输出 rank 将返回该进程的全局排名,您可以在后续通信中使用。

    顺便说一句,MPI_Cart_coords 执行相反的方向,即从排名到坐标。

    【讨论】:

      【解决方案2】:

      MPI_Cart_shift 只能在任何主要方向上找到邻居,但不能在对角线 - 你必须自己实现它,这并不难。笛卡尔移位本身只不过是一个方便的函数,它封装了对 MPI_Cart_coords 和 MPI_Cart_rank 的调用:

      //
      // The following is equivalent to
      // MPI_Cart_shift(cart_comm, i, disp, &rank_source, &rank_dest);
      //
      
      // Obtain the rank of the calling process and translate it into coordinates
      int rank, coords[ndims];
      MPI_Comm_rank(cart_comm, &rank);
      MPI_Cart_coords(cart_comm, rank, ndims, coords);
      
      int mycoord_i = coords[i];
      
      // Compute the coordinates of the destination in direction i and convert them into rank
      coords[i] = mycoord_i + disp;
      // Take care of non-periodic dimensions
      if (!periods[i] && (coords[i] >= dims[i] || coords[i] < 0))
         rank_dest = MPI_PROC_NULL;
      else
         MPI_Cart_rank(cart_comm, coords, &rank_dest);
      
      // Compute the coordinates of the source in direction i and convert them into rank
      coords[i] = mycoord_i - disp;
      // Take care of non-periodic dimensions
      if (!periods[i] && (coords[i] >= dims[i] || coords[i] < 0))
         rank_source = MPI_PROC_NULL;
      else
         MPI_Cart_rank(cart_comm, coords, &rank_source);
      

      请注意,对于非周期性维度,应如何明确处理越界。对于周期性的,MPI_Cart_rank 本身会折叠坐标。您的笛卡尔拓扑是周期性的,因此可以跳过检查(不推荐)。

      您可以轻松地修改上面的代码以产生二维或更多维度的偏移,然后使用它来枚举所有可能的位移和方向组合,以找到位于给定面上的等级。例如:

      int rank, coords[ndims];
      MPI_Comm_rank(cart_comm, &rank);
      MPI_Cart_coords(cart_comm, rank, ndims, coords);
      int my_coord1 = coords[1];
      int my_coord2 = coords[2];
      coords[1] = my_coord1 + 1;
      coords[2] = my_coord2 + 1;
      MPI_Cart_rank(cart_comm, coords, &rank_dest);
      coords[1] = my_coord1 - 1;
      coords[2] = my_coord2 - 1;
      MPI_Cart_rank(cart_comm, coords, &rank_source);
      

      当由 R0 执行时,将在rank_dest 中为您提供 R6 等级。如果您在单独的例程中提取代码并调用它MyMPI_Cart_shift2:

      MyMPI_Cart_shift2(cart_comm, 1, 1, 2, 1, &rank_source, &rank_dest);
      

      另一种选择是使用MPI_Cart_sub 将笛卡尔拓扑拆分为平行于面的平板。然后,您可以直接执行仅涉及任何给定平板中的等级的通信。

      【讨论】:

        【解决方案3】:

        您忘记标记 R5。没有我能想到的直接方法。但这是一种间接的方式:

        (1) 对于坐标为 (A,y,z) 的任何等级,请考虑坐标:(A,y+1,z+1), (A,y-1,z-1), (A,y+1,z-1) 和 (A,y-1,z+1) - 它们可以是 4 个对角线邻居。显然,当考虑例如减号时z-1,很明显 z-1 &gt;= 0 和考虑加号时,例如y+1 &lt;= (dimension_in_y - 1)。例如考虑 R5(您忘记标记)。 R5 根据 MPI 具有坐标 R5(0,1,0)。它可以有 4 个对角线邻居:(0,1+1,0+1), (0,1-1,0-1),(0,1+1,0-1),(0,1-1,0+1) - 其中只有第四个存在(这很清楚,因为没有邻居可以有 负坐标 并且每个坐标必须少 1 大于该方向的尺寸)。接下来只需查询MPI_coordinate_to_rank()。

        (2) 另一种方法是查询right 和left 邻居的front 和back 邻居(这在性能方面会很糟糕)。

        (3) 要将其推广到 8 个邻居 - 您还需要改变 X 坐标 - 但您的问题仅限于立方体的面。

        【讨论】:

        • 请检查进程坐标。它们不符合 MPI 笛卡尔坐标。
        猜你喜欢
        • 2012-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-18
        • 2011-07-19
        • 1970-01-01
        • 2016-04-06
        相关资源
        最近更新 更多