2.4.2. MPI_Send と MPI_Recv
1#include <mpi.h>
2#include <iostream>
3#include <cstdlib>
4
5/* 後で定義する関数の前方宣言 */
6void send_data();
7void recv_data();
8
9/*
10 * 2つのプロセスの間で配列データを送る
11 *
12 * 実行方法: mpiexec -n 2 mpi_sample2
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 != 2) {
25 std::cerr << "Run this program in MPI with 2 processes." << std::endl;
26 return EXIT_FAILURE;
27 }
28
29 // send data from rank 0 to rank 1
30 if (my_rank == 0) {
31 send_data();
32 } else {
33 recv_data();
34 }
35
36 MPI_Finalize();
37 return EXIT_SUCCESS;
38}
39
40void send_data()
41{
42 double send_data[10];
43 for (int i = 0; i < 10; i++) {
44 send_data[i] = (double) i;
45 }
46 const double *data_address = &send_data[0];
47 int data_count = 10;
48 std::cout << "Sending data." << std::endl;
49 std::cout << "send_data: [";
50 for (int i = 0; i < 10; i++)
51 {
52 std::cout << " " << send_data[i];
53 }
54 std::cout << " ]" << std::endl;
55 MPI_Send(
56 data_address, /* データ(バッファ)の先頭アドレス。MPIはここから読み出すだけなのでconst */
57 data_count, /* 要素数 */
58 MPI_DOUBLE, /* 送るデータの型。バッファの型に合わせる。間違えると受信データがおかしくなる。 */
59 1, /* 送り先のrank */
60 0, /* タグと呼ぶ数値。同時期に同じ送信先に違う意味合いのデータを送る時に区別するための番号。自分で値を決める */
61 MPI_COMM_WORLD /* ノードを用途別にグループ分けした時にグループを識別するための値 */
62 );
63}
64
65void recv_data()
66{
67 double data[10];
68 double *data_address = &data[0];
69 int data_count = 10;
70 MPI_Status st; /* 通信の成否コードを受け取るための変数 */
71
72 std::cout << "Receiving data." << std::endl;
73 MPI_Recv(
74 data_address, /* データ(バッファ)の先頭アドレス。MPIはここに書き込むので非const */
75 data_count, /* 受信するデータの個数。 */
76 MPI_DOUBLE, /* 受信するデータの型。 */
77 0, /* 送り元のrank */
78 0, /* タグ */
79 MPI_COMM_WORLD,
80 &st
81 );
82 std::cout << "recv_data: [";
83 for (int i = 0; i < 10; i++)
84 {
85 std::cout << " " << data[i];
86 }
87 std::cout << " ]" << std::endl;
88}
この例では最も基本的な通信関数の MPI_Send と MPI_Recv を使っています。
プロセス数 2 で起動されると、rank 0 として起動されたプロセスの側では 送信を行い、rank 1 として起動されたプロセスの側では受信を行います。
このプログラムは 2 プロセスとして起動された場合にだけ対応しているので プログラムの入り口でプロセス数のチェックをしています。
送信データは配列として用意します。配列の先頭アドレス、送るデータの 要素数、データの型のコード、送り先相手などを指定して MPI_Send を呼びます。
受信側では受信データを受け取る配列を用意します。受信データの個数が 分かっていないと配列を用意できませんが、ここでは10個で固定になっています。 受信側も、送信側と似たような情報を指定して MPI_Recv を呼びます。
このサンプルのコンパイルと実行した例を示します。:
$ mpic++ -o mpi_sample2 mpi_sample2.cpp
$ mpiexec -n 2 mpi_sample2
Receiving data.
Sending data.
send_data: [ 0 1 2 3 4 5 6 7 8 9 ]
recv_data: [ 0 1 2 3 4 5 6 7 8 9 ]