集合通信の例: allgather

プログラム: mv.c

include 
#include "mpi.h"
#define N 4
#define M 4
main(int argc, char* argv[]) {

  int  A[M][N] = {{1, 2, 3, 4},
                  {5, 6, 7, 8},
                  {9, 10, 11 ,12},
                  {13, 14, 15, 16}}, local_A[N][M];
  int  X[N] = {1, 2, 3, 4}, local_X[N];
  int  Y[N], local_Y[N];
  int local_m, local_n;
  int i,j;

  int p;
  int myrank;
  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &p);
  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

  local_m = M/p;
  local_n = N/p;

  MPI_Scatter(A, local_m*N, MPI_INT, local_A,
              local_m*N, MPI_INT, 0, MPI_COMM_WORLD);

  MPI_Scatter(X, local_n, MPI_INT, local_X, local_n, MPI_INT,
              0, MPI_COMM_WORLD);

  MPI_Allgather(local_X, local_n, MPI_INT, X, local_n, MPI_INT,
                MPI_COMM_WORLD);
  for (i = 0; i < local_m; i++) {
    local_Y[i] = 0;
    for (j = 0; j <  N; j++)
      local_Y[i] = local_Y[i] + local_A[i][j]*X[j];
  }

  MPI_Gather(local_Y, local_m, MPI_INT, Y, local_m, MPI_INT, 0,
             MPI_COMM_WORLD);

  if (myrank == 0){
    for (i=0; i < M; i++) printf("%d ", Y[i]);
    printf("\n");
  }

  MPI_Finalize();

}

MPI_Allgather

int MPI_Allgather ( 
    void *sendbuf,        // starting address of send buffer (choice) 
    int sendcount,        // number of elements in send buffer (integer) 
    MPI_Datatype sendtype,// data type of send buffer elements (handle) 
    void *recvbuf, 
    int recvcount,        // number of elements received from any process (integer) 
    MPI_Datatype recvtype,// data type of receive buffer elements (handle) 
    MPI_Comm comm         // communicator (handle) 
    )

コンパイルと実行

   % cc -64 allgather.c -lmpi
   % mpirun -np 2 ./a.out

解説

MxNの配列と大きさMのベクトルの積を計算する.本来ならば,配列AとベクトルXは外部から 与えられるのであるがここではプログラム中に定数として与えてある.

この計算を並列に行うため,まずはじめに配列とベクトルを各プロセスに分散する(MPI_Scatter). その際,各プロセスには配列,ベクトル共にM/p行分の大きさを持つ部分配列local_Aと部分ベクトル local_Xが格納される.ここで,答えを格納するベクトルYに対し,Y[k](0<=k<=M)を計算する には,各プロセス共,ベクトルX全体が必要となる.そのため,すべてのプロセスが同じXを 持つためにMPI_Allgatherを使用する.(本来Xは外部から入力として与えられ,各プロセスは 最初から持っていないと仮定する.実際はプログラム中に与えられているが).次に,各プロセス ごとにローカルな配列・ベクトル計算を行い,最後に,ローカルな結果local_Yをルートプロセスに 集め(MPI_Gather),プリントする.