NSSC/Exercise_01/examples/MPI_Cart_coords.cpp

92 lines
3.0 KiB
C++

#include <iostream>
#include <initializer_list>
#include <mpi.h>
/* Quick and dirty primality test */
bool is_prime(int num) {
if (num == 2 || num == 3) { return true; }
if ((num % 2) == 0 || (num % 3) == 0) { return false; }
for (int div = 5; div * div <= num; div += 6) {
if ((num % div) == 0 || ((num + 2) % div) == 0) { return false; }
}
return true;
}
int main(int argn, char* argv[]) {
MPI_Init(nullptr, nullptr);
int mpi_size;
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
// Check if a 2D grid is (more or less) possible
if ((mpi_size > 2) && is_prime(mpi_size)) {
// Print warning only once (by rank 0)
int mpi_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
if (mpi_rank == 0) {
std::cout << "Warning: 2D grid degenerates to 1D." << std::endl;
}
}
// Group processes into a cartesian communication topology
int mpi_dims[2] = {0, 0};
MPI_Dims_create(mpi_size, 2, mpi_dims);
// Setup a cartesian topology communicator (NON-cyclic)
const int mpi_periods[2] = {false, false};
MPI_Comm mpi_comm_grid;
MPI_Cart_create(
MPI_COMM_WORLD, // Old Communicator
2, // number of dimensions
mpi_dims, // grid dimensions
mpi_periods, // grid periodicity
true, // allow process reordering
&mpi_comm_grid
);
// Get rank with respect to the grid communicator
int mpi_rank;
MPI_Comm_rank(mpi_comm_grid, &mpi_rank);
// Get coordinates with respect to the grid communicator
int mpi_coords[2];
MPI_Cart_coords(mpi_comm_grid, mpi_rank, 2, mpi_coords);
// Get direct neightbours in the communication grid
struct { int north; int east; int south; int west; } mpi_neighbours;
// Get X-direction (dim 0) neightbours
MPI_Cart_shift(
mpi_comm_grid, // grid communicator
0, // axis index (0 <-> X)
1, // offset
&(mpi_neighbours.west), // negated offset neightbour
&(mpi_neighbours.east) // offset neightbour
);
// Get Y-direction (dim 1) neightbours
MPI_Cart_shift(
mpi_comm_grid,
1, // axis index (1 <-> X)
1,
&(mpi_neighbours.south),
&(mpi_neighbours.north)
);
// Print grid communicator location and with direct neighbors (offset +-1)
std::cout << "Rank " << mpi_rank << ": Coords ("
<< mpi_coords[0] << ", "
<< mpi_coords[1] << ") - Neighbours: ";
if (mpi_neighbours.west != MPI_PROC_NULL) { std::cout << mpi_neighbours.west << ' '; }
if (mpi_neighbours.east != MPI_PROC_NULL) { std::cout << mpi_neighbours.east << ' '; }
if (mpi_neighbours.south != MPI_PROC_NULL) { std::cout << mpi_neighbours.south << ' '; }
if (mpi_neighbours.north != MPI_PROC_NULL) { std::cout << mpi_neighbours.north << ' '; }
std::cout << std::endl;
MPI_Finalize();
return 0;
}