2.4.4. MPI_Scatter
1#include <mpi.h>
2
3#include <iostream>
4#include <vector>
5#include <cstdlib>
6
7/*
8 * 配列データを区切って各プロセスに分配する
9 *
10 * 実行方法: mpiexec -n 4 mpi_sample4
11 * プロセス数は 1 〜 9 まで指定可能
12 */
13
14int main(int argc, char *argv[])
15{
16 MPI_Init(&argc, &argv);
17
18 int num_procs;
19 int my_rank;
20
21 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
22 MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
23
24 if (num_procs > 10)
25 {
26 std::cerr << "Number of processes must be 10 at max." << std::endl;
27 return EXIT_FAILURE;
28 }
29
30 int send_data_count;
31 if (my_rank == 0)
32 {
33 send_data_count = 10;
34 } else
35 {
36 send_data_count = 0;
37 }
38 int total_send_data_count = send_data_count * num_procs;
39 std::vector<double> send_data(total_send_data_count, 0);
40 const double *send_data_address = &send_data[0];
41
42 int recv_data_count = 10;
43 std::vector<double> recv_data(recv_data_count, 0);
44 double *recv_data_address = &recv_data[0];
45
46 if (my_rank == 0)
47 {
48 /* 送り元rankでは送信データを用意する */
49 for (int i = 0; i < total_send_data_count; i++)
50 {
51 send_data[i] = i;
52 }
53
54 std::cout << "rank: 0, send_data: [" << std::endl;
55 for (int k = 0; k < num_procs; k++)
56 {
57 for (int i = 0 ; i< send_data_count; i++)
58 {
59 std::cout << " " << send_data[k*send_data_count + i];
60 }
61 std::cout << std::endl;
62 }
63 std::cout << "]" << std::endl;
64 }
65
66 MPI_Scatter(
67 send_data_address,
68 send_data_count, // rank == 0 でのみ正
69 MPI_DOUBLE,
70 recv_data_address, // 全rankで受信
71 recv_data_count,
72 MPI_DOUBLE,
73 0, /* 送り元とするrank */
74 MPI_COMM_WORLD
75 );
76
77 // 受信できたデータを表示する
78 std::cout << "rank: " << my_rank << ", recv_data: [";
79 for (int i = 0; i < 10; i++)
80 {
81 std::cout << " " << recv_data[i];
82 }
83 std::cout << " ]" << std::endl;
84
85 MPI_Finalize();
86 return EXIT_SUCCESS;
87}
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 ]