2.3.3. MPI_Bcast

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

/*
 * 1つのプロセスから、残りの全てのプロセスに同じデータを送る
 * データの分割などはしない
 *
 * 実行方法 : mpiexec -n 2 mpi_sample3
 * プロセス数を変えて実行できる。
 */

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

    double data[10];

    /*
     * 送信データは rank == 0 でだけ作成する
     */
    double *data_addr = &data[0];
    int data_count = 10;
    if (my_rank == 0)
    {
        for (int i = 0; i < 10; i++)
        {
            data[i] = i;
        }
    }

    /*
     * BCast を全プロセスで呼び出す
     *
     * 第4引数と合致する rank のプロセスに於いては bcast は送信処理をする。
     * それ以外の rank のプロセスでは bcast は受信処理をする。
     */
    MPI_Bcast(
        data_addr, /* rank == 0 においては送信バッファ、それ以外では受信バッファ */
        data_count, /* 要素の個数 */
        MPI_DOUBLE, /* 要素のデータ型 */
        0, /* 送信元として働く rank の番号 */
        MPI_COMM_WORLD
    );

    std::cout << "rank: " << my_rank << ", data: [";
    for (int i = 0; i < 10; i++)
    {
        std::cout << " " << data[i];
    }
    std::cout << " ]" << std::endl;

    MPI_Finalize();
    return EXIT_SUCCESS;
}

Download the source code

MPIでは、全てのrankで一斉に同じ関数を呼ぶことで通信を行うタイプの関数が多く存在します。 その中の基本的な関数 MPI_Bcast の例です。

MPI_Bcast にはデータを格納する配列を1つだけ渡します。全てのrankで渡しますが、 ルートとして指定したrankにおいては送信データとして使われ、配列から値が読み出されて 他のrankに送信されます。残りのrankでは配列が受信バッファとして使われ、ルートrankから 送られてきたデータがそこに格納されます。 その結果、関数が終わった時点で配列の内容は全てのrankで同一になります。

パソコンlinuxのopenmpiで実行すると次のようになります。:

$ mpic++ -o mpi_sample3 mpi_sample3.cpp
$ mpiexec -n 4 mpi_sample3
rank: 0, data: [ 0 1 2 3 4 5 6 7 8 9 ]
rank: 1, data: [ 0 1 2 3 4 5 6 7 8 9 ]
rank: 2, data: [ 0 1 2 3 4 5 6 7 8 9 ]
rank: 3, data: [ 0 1 2 3 4 5 6 7 8 9 ]

ソースと照らし合わせて見ると、rank 0 で用意したデータが全rankに伝達されたことがわかります。