2.3.4. MPI_Scatter

 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
#include <mpi.h>

#include <iostream>
#include <vector>
#include <cstdlib>

/*
 * 配列データを区切って各プロセスに分配する
 *
 * 実行方法: mpiexec -n 4 mpi_sample4
 * プロセス数は 1 〜 9 まで指定可能
 */

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

    int send_data_count;
    if (my_rank == 0)
    {
        send_data_count = 10;
    } else
    {
        send_data_count = 0;
    }
    int total_send_data_count = send_data_count * num_procs;
    std::vector<double> send_data(total_send_data_count, 0);
    const double *send_data_address = &send_data[0];

    int recv_data_count = 10;
    std::vector<double> recv_data(recv_data_count, 0);
    double *recv_data_address = &recv_data[0];

    if (my_rank == 0)
    {
        /* 送り元rankでは送信データを用意する */
        for (int i = 0; i < total_send_data_count; i++)
        {
            send_data[i] = i;
        }

        std::cout << "rank: 0, send_data: [" << std::endl;
        for (int k = 0; k < num_procs; k++)
        {
            for (int i = 0 ; i< send_data_count; i++)
            {
                std::cout << " " << send_data[k*send_data_count + i];
            }
            std::cout << std::endl;
        }
        std::cout << "]" << std::endl;
    }

    MPI_Scatter(
        send_data_address,
        send_data_count, // rank == 0 でのみ正
        MPI_DOUBLE,
        recv_data_address, // 全rankで受信
        recv_data_count,
        MPI_DOUBLE,
        0, /* 送り元とするrank */
        MPI_COMM_WORLD
        );

    // 受信できたデータを表示する
    std::cout << "rank: " << my_rank << ", recv_data: [";
    for (int i = 0; i < 10; i++)
    {
        std::cout << " " << recv_data[i];
    }
    std::cout << " ]" << std::endl;

    MPI_Finalize();
    return EXIT_SUCCESS;
}

Download the source code

MPI_Scatter では、グループ操作のルートとして指定した rank で 用意した配列データを等しい個数ずつ、全てのrankに分配します。

ルートrankを含む全てのrankでは分配された分のデータだけを受信します。

送信するのはルートrankだけですが、関数のインタフェース上は 全てのrankで送信バッファと受信バッファの双方を指定します。

コンパイルと実行例を示します。:

$ mpic++ -o mpi_sample4 mpi_sample4.cpp
$ mpiexec -n 4 mpi_sample4
rank: 0, send_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
]
rank: 0, recv_data: [ 0 1 2 3 4 5 6 7 8 9 ]
rank: 3, recv_data: [ 30 31 32 33 34 35 36 37 38 39 ]
rank: 1, recv_data: [ 10 11 12 13 14 15 16 17 18 19 ]
rank: 2, recv_data: [ 20 21 22 23 24 25 26 27 28 29 ]