2.4.5. MPI_Gather

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

Download the source code

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
]