2.3.5. MPI_Gather¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #include <mpi.h>
#include <iostream>
#include <cstdlib>
#include <vector>
/*
* 各ノードで計算した配列データを1つのノードに集める
*
* 実行方法: mpiexec -n 4 mpi_sample5
*/
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
int num_procs;
int my_rank;
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
if (num_procs > 10)
{
std::cerr << "Number of processes must be 10 at max." << std::endl;
return EXIT_FAILURE;
}
/*
* 全rankでそれぞれ10個ずつデータを生成する
*/
int send_data_count = 10;
std::vector<double> send_data(send_data_count, 0);
const double *send_data_address = &send_data[0];
for (int i = 0; i < send_data_count; i++)
{
send_data[i] = my_rank * 10 + i;
}
std::cout << "rank: " << my_rank << ", send_data: [";
for (int i = 0; i < send_data_count; i++)
{
std::cout << " " << send_data[i];
}
std::cout << " ]" << std::endl;
/*
* 受信バッファは rank == 0 でのみ割り当てる。
*/
int recv_data_count;
if (my_rank == 0)
{
// rank 0 でデータを受信する。送信もして、自身で受信する。
recv_data_count = 10;
}
else
{
recv_data_count = 0;
}
int total_recv_data_count = recv_data_count * num_procs;
std::vector<double> recv_data(total_recv_data_count, 0);
double *recv_data_address = &recv_data[0];
MPI_Gather(
send_data_address,
send_data_count,
MPI_DOUBLE,
recv_data_address,
recv_data_count, // rank == 0 でのみ正
MPI_DOUBLE,
0,
MPI_COMM_WORLD
);
if (my_rank == 0)
{
// rank 0 でしか受信しないので、ここでデータを表示する。
std::cout << "rank: 0, recv_data: [" << std::endl;
for (int k = 0; k < num_procs; k++)
{
for (int i = 0 ; i< recv_data_count; i++)
{
std::cout << " " << recv_data[k*recv_data_count + i];
}
std::cout << std::endl;
}
std::cout << "]" << std::endl;
}
MPI_Finalize();
return EXIT_SUCCESS;
}
|
MPI_Gather 関数の機能は MPI_Scatter の逆で、各rankで用意した等しい長さの 配列データをルート rank で用意した全ノード分の配列に集めるというものです。
openmpiによる実行例です。:
$ mpic++ -o mpi_sample5 mpi_sample5.cpp
$ mpiexec -n 5 mpi_sample5
rank: 2, send_data: [ 20 21 22 23 24 25 26 27 28 29 ]
rank: 3, send_data: [ 30 31 32 33 34 35 36 37 38 39 ]
rank: 4, send_data: [ 40 41 42 43 44 45 46 47 48 49 ]
rank: 1, send_data: [ 10 11 12 13 14 15 16 17 18 19 ]
rank: 0, send_data: [ 0 1 2 3 4 5 6 7 8 9 ]
rank: 0, recv_data: [
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
]