MPI_Reduce

いちごパック > MPIの解説 > MPI_Reduce

インターフェース

#include <mpi.h>
int MPI_Reduce(const void* psendbuf, void* precvbuf,
               int count, MPI_Datatype datatype,
               MPI_Op op, int root, MPI_Comm comm);
root自身を含むすべてのプロセスのデータをrootで指定されたプロセスに送信し、 MPI_Opで指定された演算を適用したうえで、 rootで指定されたプロセスのバッファprecvbufに格納します。
MPI_Opで指定された演算中にエラーが発生した場合、エラー値を返す機能は用意されていません。 この場合はエラーハンドラが呼び出されます。 エラーハンドラはデフォルトでMPI_Abort()を呼び出しますが、 このハンドラを変更し処理を続行した場合、返される結果は無意味はものになります。
この関数は通信完了まで待機します。 この関数を使う場合は、同じ受信型を指定してすべてのプロセスで呼び出す必要があります。
成功した場合の戻り値はMPI_SUCCESSです。失敗した場合はそれ以外のエラー値が返されます。
引数内容
psenddata送信データの先頭へのポインタです。
precvbuf受信バッファの先頭へのポインタです。rootで指定したプロセス以外では無視されます。
count送受信データの要素数です。
datatype送受信データの型です。
op使用する演算を指定します。
root全データを受信するプロセスのランク番号です。
comm送受信を行うプロセスの所属プロセスグループを指定します。MPI_COMM_WORLDを指定するとすべてのプロセスが所属するプロセスグループになります。

サンプルプログラム

各プロセスで、自身のランク番号に1を加えた値を生成します。 はじめに、それらすべての値をランク番号0を持つプロセスに集めて、それらを表示します。 その後、いくつかのMPI_Opに対してMPI_Reduce()を呼び出し、それらの結果を表示します。

#include <mpi.h>
#include <stdint.h>
#include <iostream>
#include <vector>

#define RANK_MASTER 0

#define ABORT_INIT 1
#define ABORT_ICHIGO 15


int main( int argc, char** argv )
{
    int num_processes = 1;
    int process_rank = 0;
    int ret;
    int32_t localdata;
    int32_t ichigoval;
    struct {
        int val;
        int index;
    } localdata_maxloc, ichigoval_maxloc;

    ret = MPI_Init(&argc, &argv);
    if (ret == MPI_SUCCESS)
    ret = MPI_Comm_size(MPI_COMM_WORLD, &num_processes);
    if (ret == MPI_SUCCESS)
        ret = MPI_Comm_rank(MPI_COMM_WORLD, &process_rank);
    if (ret != MPI_SUCCESS) {
        // error
        MPI_Abort(MPI_COMM_WORLD, ABORT_INIT);
    }

    localdata = process_rank + 1;

    if (process_rank == RANK_MASTER) {
        std::vector<int32_t> ichigobuf;
        ichigobuf.resize(num_processes);
        ret = MPI_Gather(
            &localdata, 1, MPI_INT32_T,
            &ichigobuf[0], 1, MPI_INT32_T,
            RANK_MASTER, MPI_COMM_WORLD );
        if (ret == MPI_SUCCESS) {
            int ichigoloop;

            std::cout << "ichigosample: data = ";
            for (ichigoloop = 0; ichigoloop < num_processes; ichigoloop++)
                std::cout << ichigobuf[ichigoloop] << " ";
            std::cout << std::endl;
        }
    } else {
        ret = MPI_Gather(
            &localdata, 1, MPI_INT32_T,
            NULL, 1, MPI_INT32_T,
            RANK_MASTER, MPI_COMM_WORLD );
    }
    if (ret != MPI_SUCCESS) {
        MPI_Abort(MPI_COMM_WORLD, ABORT_ICHIGO);
    }

    ret = MPI_Reduce(
        &localdata,
        (process_rank == RANK_MASTER) ? &ichigoval : NULL,
        1, MPI_INT32_T,
        MPI_SUM, RANK_MASTER, MPI_COMM_WORLD);
    if (ret != MPI_SUCCESS) {
        MPI_Abort(MPI_COMM_WORLD, ABORT_ICHIGO);
    }
    if (process_rank == RANK_MASTER) {
        std::cout << "ichigosample: SUM = " << ichigoval << std::endl;
    }

    ret = MPI_Reduce(
        &localdata,
        (process_rank == RANK_MASTER) ? &ichigoval : NULL,
        1, MPI_INT32_T,
        MPI_PROD, RANK_MASTER, MPI_COMM_WORLD);
    if (ret != MPI_SUCCESS) {
        MPI_Abort(MPI_COMM_WORLD, ABORT_ICHIGO);
    }
    if (process_rank == RANK_MASTER) {
        std::cout << "ichigosample: PROD = " << ichigoval << std::endl;
    }

    ret = MPI_Reduce(
        &localdata,
        (process_rank == RANK_MASTER) ? &ichigoval : NULL,
        1, MPI_INT32_T,
        MPI_MAX, RANK_MASTER, MPI_COMM_WORLD);
    if (ret != MPI_SUCCESS) {
        MPI_Abort(MPI_COMM_WORLD, ABORT_ICHIGO);
    }
    if (process_rank == RANK_MASTER) {
        std::cout << "ichigosample: MAX = " << ichigoval << std::endl;
    }

    localdata_maxloc.val = localdata;
    localdata_maxloc.index = process_rank + 100;
    ret = MPI_Reduce(
        &localdata_maxloc,
        (process_rank == RANK_MASTER) ? &ichigoval_maxloc : NULL,
        1, MPI_2INT,
        MPI_MAXLOC, RANK_MASTER, MPI_COMM_WORLD);
    if (ret != MPI_SUCCESS) {
        MPI_Abort(MPI_COMM_WORLD, ABORT_ICHIGO);
    }
    if (process_rank == RANK_MASTER) {
        std::cout
            << "ichigosample: MAXLOC = " << ichigoval_maxloc.val
            << ", " << ichigoval_maxloc.index << std::endl;
    }

    MPI_Finalize();
    return 0;
}


4つのプロセスで動作させたときの出力結果の1例は次の通りです。
ichigosample: data = 1 2 3 4 
ichigosample: SUM = 10
ichigosample: PROD = 24
ichigosample: MAX = 4
ichigosample: MAXLOC = 4, 103

関連ページ

  • MPIの解説 目次
  • MPI_Op定数
  • MPI_Datatype定数