C++でOpenMPI入門8 コミュニケータ2

というわけで早速, 2次元座標で前回と同様のことをしてみる.

#include <iostream>
#include <mpi.h>

int main(int argc, char **argv)
{
    MPI::Init(argc, argv);

    int procs = MPI::COMM_WORLD.Get_size();

    int dims[2] = {0, 0};
    MPI::Compute_dims(procs, 2, dims);

    bool periods[2] = {true, true};
    MPI::Cartcomm COMM_CART = MPI::COMM_WORLD.Create_cart(
        2, dims, periods, true);

    int rank = COMM_CART.Get_rank();
    int coords[2];
    COMM_CART.Get_coords(rank, 2, coords);

    int send_value = rank;
    int recv_value = -1;

    int src_rank, dest_rank;
    COMM_CART.Shift(0, 1, src_rank, dest_rank);

    const int TAG = 0;
    COMM_CART.Sendrecv(&send_value, 1, MPI::INT, dest_rank, TAG,
                       &recv_value, 1, MPI::INT, src_rank , TAG);
    std::cout << "rank = " << rank
              << " (" << coords[0] << ", " << coords[1]
              << ") : recv_value = " << recv_value << std::endl;

    MPI::Finalize();
}

実行してみた結果.

$ mpic++ test.cpp && mpirun -np 9 ./a.out 
rank = 0 (0, 0) : recv_value = 6
rank = 1 (0, 1) : recv_value = 7
rank = 2 (0, 2) : recv_value = 8
rank = 3 (1, 0) : recv_value = 0
rank = 4 (1, 1) : recv_value = 1
rank = 5 (1, 2) : recv_value = 2
rank = 6 (2, 0) : recv_value = 3
rank = 7 (2, 1) : recv_value = 4
rank = 8 (2, 2) : recv_value = 5

2次元的な座標はランクの隣に括弧で示してある. ちゃんと1番目の座標(クドいようだが, Shift的には0番目)でひとつ繰り上がっていることがわかる.

新しいのはGet_coordsだけです. これはランクから座標をとってくる関数. 2番目の引数は次元数. その逆としてGet_cart_rankというのもあります. これは座標からランクをとってくる関数. 例えば, "int rank = COMM_CART.Get_cart_rank(coords);"みたいに使えたと思われ.

2次元くらいだとまだイメージわきますが, 3次元以上になってくると便利感でてきますね.