MPI_Cart_Shift.Corner Neighborhood

enter image description here

I need to create a communicator with a cube topology, and then select a cube face using MPI_Cart_Shift, implemented messaging between processes on the edge. For example, I am a process with a rank of 0 (R0), my neighborhood is R2, R4, R6 (the bottom face of the cube). I can find R2 and R4, but I can not figure out how to find R6. My code is:

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

I will try to add something like this MPI_Cart_shift (comm, 2, 1, & diagonal and diagonal X); But for R0, he shows me R1, and I understand ... How can I get angular neighborhoods?

+5
source share
3 answers

You can use MPI_Cart_rank to find the information you need.

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

Here comm is a communicator with a Cartesian topology. coords - an integer array (the size of this array is the number of dimensions of the Cartesian topology) containing the coordinate of the process (in your case, 1.1.0 for R6). Then the output rank will return the global rank of this process, which you can use in the subsequent connection.

BTW, MPI_Cart_coords performs the opposite direction, that is, from rank to coordinates.

+2
source

MPI_Cart_shift can only find neighbors in any of the main directions, but not diagonally - you must implement it yourself, which is not so difficult to do. The Cartesian shift itself is nothing more than a convenience function that wraps the calls to MPI_Cart_coords and 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); 

Please note that for non-periodic measurements, you must explicitly handle the failure. For periodic, MPI_Cart_rank itself performs coordinate folding. Your Cartesian topology is periodic, so checks may be skipped (not recommended).

You can easily adapt the code above to shift in two or more dimensions, and then use it to list all possible combinations of movements and directions to find the ranks that lie on that person. For instance:

 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); 

will give you the rank of R6 in rank_dest when doing R0. If you extract the code in a separate procedure and call it MyMPI_Cart_shift2 :

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

Another option is to use MPI_Cart_sub to partition the Cartesian topology into slabs parallel to the faces. Then you can directly carry out communication involving only ranks in any given plate.

+1
source

You forgot to designate R5. I do not think about a direct approach. But here is an indirect way:

(1) For any rank whose coordinates (A,y,z) , we consider the coordinates: (A,y+1,z+1), (A,y-1,z-1), (A,y+1,z-1) and (A,y-1,z+1) - these can be 4 diagonal neighbors. It is clear that when considering the minus, for example. z-1 , it is clear that z-1 >= 0 and when considering the plus for, for example, y+1 <= (dimension_in_y - 1) . For example, consider R5 (which you forgot on the label). R5 in accordance with MPI has the coordinates R5(0,1,0) . It can have 4 diagonal neighbors: (0,1+1,0+1), (0,1-1,0-1),(0,1+1,0-1),(0,1-1,0+1) - of which only the fourth exists (this is clear, since no neighbor can have negative coordinates, and each coordinate must be 1 less than the dimension in this direction). Then just request MPI_coordinate_to_rank() .

(2) Another method is to query the right and left neighbors about their front and back neighbors (this will be poor in performance).

(3) To generalize it to 8 neighbors, you will also need to change the X coordinate, but your question is limited to the cube line.

0
source

Source: https://habr.com/ru/post/1237797/


All Articles