2015年11月30日 星期一

MPI Three-Group Pipeline

底下的MPI範例很有趣, 來自於5.6.3. Inter-Communication Examples
它主要是想要介紹建立三個節點, 彼此之間使用communicator串起來, 模擬成pipeline的運作方式.
希望產的效果如下圖:

程式碼我有動過, 如下
//http://www.mpi-forum.org/docs/mpi-1.1/mpi-11-html/node114.html
//Groups 0 and 1 communicate. Groups 1 and 2 communicate.
//Therefore, group 0 requires one inter-communicator, group 1 requires two inter-communicators,
//and group 2 requires 1 inter-communicator.

//int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm)
//int MPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm *newintercomm)
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char **argv){
        MPI_Comm   myComm;       /* intra-communicator of local sub-group */
        MPI_Comm   myFirstComm;  /* inter-communicator */
        MPI_Comm   mySecondComm; /* second inter-communicator (group 1 only) */
        int membershipKey = 0, rank =0, buffer = 0;
        MPI_Status status;
        double start_time, recive_time;

        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);

        /* User code must generate membershipKey in the range [0, 1, 2] */
        membershipKey = rank % 3;
        start_time = MPI_Wtime();

        /* Build intra-communicator for local sub-group */
        MPI_Comm_split(MPI_COMM_WORLD, membershipKey, rank, &myComm);

        /* Build inter-communicators.  Tags are hard-coded. */
        if (membershipKey == 0){
                /* Group 0 communicates with group 1. */
                MPI_Intercomm_create( myComm, 0, MPI_COMM_WORLD, 1, 1, &myFirstComm);
        }
        else if (membershipKey == 1){
                /* Group 1 communicates with groups 0 and 2. */
                MPI_Intercomm_create( myComm, 0, MPI_COMM_WORLD, 0, 1, &myFirstComm);
                MPI_Intercomm_create( myComm, 0, MPI_COMM_WORLD, 2, 12, &mySecondComm);
        }
        else if (membershipKey == 2){
                /* Group 2 communicates with group 1. */
                MPI_Intercomm_create( myComm, 0, MPI_COMM_WORLD, 1, 12, &mySecondComm);
        }

        switch(membershipKey){
                case 0:
                        buffer = 100;
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        MPI_Send(&buffer, 1, MPI_INT, 0, 0, myFirstComm);
                        MPI_Recv(&buffer, 1, MPI_INT, 0, 0, myFirstComm, &status);
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        break;
                case 1:
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        MPI_Recv(&buffer, 1, MPI_INT, 0, 0, myFirstComm, &status);
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        buffer = 200;
                        MPI_Send(&buffer, 1, MPI_INT, 0, 0, myFirstComm);
                        MPI_Send(&buffer, 1, MPI_INT, 0, 0, mySecondComm);
                        break;
                case 2:
                        MPI_Recv(&buffer, 1, MPI_INT, 0, 0, mySecondComm, &status);
                        printf("[%d][%f]buffer=%d\n", rank, MPI_Wtime() - start_time, buffer);
                        break;
        }

        MPI_Comm_free(&myComm);
        switch(membershipKey){/* free communicators appropriately */
                case 1:
                        MPI_Comm_free(&mySecondComm);
                        MPI_Comm_free(&myFirstComm);
                        break;
                case 0:
                        MPI_Comm_free(&myFirstComm);
                        break;
                case 2:
                        MPI_Comm_free(&mySecondComm);
                        break;
        }
        MPI_Finalize();
}
執行的結果如下
Starting MPI_Init...
Starting MPI_Init...
Starting MPI_Init...
[0] Ending MPI_Init
[0] Starting MPI_Comm_rank...
[0] Ending MPI_Comm_rank
[0] Starting MPI_Comm_split...
[0] Ending MPI_Comm_split
[0] Starting MPI_Intercomm_create...
[0] Ending MPI_Intercomm_create
[0][0.000326]buffer=100
[0] Starting MPI_Send with count = 1, dest = 0, tag = 0...
[0] Ending MPI_Send
[0] Starting MPI_Recv with count = 1, source = 0, tag = 0...
[0] Ending MPI_Recv from 0 with tag 0
[0][0.000408]buffer=200
[0] Starting MPI_Comm_free...
[1] Ending MPI_Init
[1] Starting MPI_Comm_rank...
[1] Ending MPI_Comm_rank
[1] Starting MPI_Comm_split...
[1] Ending MPI_Comm_split
[1] Starting MPI_Intercomm_create...
[1] Ending MPI_Intercomm_create
[1] Starting MPI_Intercomm_create...
[1] Ending MPI_Intercomm_create
[1][0.000166]buffer=0
[1] Starting MPI_Recv with count = 1, source = 0, tag = 0...
[1] Ending MPI_Recv from 0 with tag 0
[1][0.000214]buffer=100
[1] Starting MPI_Send with count = 1, dest = 0, tag = 0...
[1] Ending MPI_Send
[1] Starting MPI_Send with count = 1, dest = 0, tag = 0...
[1] Ending MPI_Send
[1] Starting MPI_Comm_free...
[1] Ending MPI_Comm_free
[1] Starting MPI_Comm_free...
[2] Ending MPI_Init
[2] Starting MPI_Comm_rank...
[2] Ending MPI_Comm_rank
[2] Starting MPI_Comm_split...
[2] Ending MPI_Comm_split
[2] Starting MPI_Intercomm_create...
[2] Ending MPI_Intercomm_create
[0] Ending MPI_Comm_free
[0] Starting MPI_Comm_free...
[0] Ending MPI_Comm_free
[0] Starting MPI_Finalize...
[0] Ending MPI_Finalize
[1] Ending MPI_Comm_free
[1] Starting MPI_Comm_free...
[1] Ending MPI_Comm_free
[1] Starting MPI_Finalize...
[2] Starting MPI_Recv with count = 1, source = 0, tag = 0...
[2] Ending MPI_Recv from 0 with tag 0
[2][0.000409]buffer=200
[2] Starting MPI_Comm_free...
[2] Ending MPI_Comm_free
[2] Starting MPI_Comm_free...
[2] Ending MPI_Comm_free
[2] Starting MPI_Finalize...
[1] Ending MPI_Finalize
[2] Ending MPI_Finalize

沒有留言: