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