110 likes | 433 Views
MPI: A Quick-Start Guide. Information Physics Soon-Hyung Yook. Outlook. MPI MPI functions MPI_Init MPI_Finalize MPI_Comm_size MPI_Comm_rank MPI_Send MPI_Receive MPI_Broadcast MPI_Scatter MPI_Reduce MPI_Gather MPI datatypes MPI_CHAR MPI_INT MPI_FLOAT MPI_DOUBLE. MPI. MPI
E N D
MPI: A Quick-Start Guide Information Physics Soon-Hyung Yook
Outlook • MPI • MPI functions • MPI_Init • MPI_Finalize • MPI_Comm_size • MPI_Comm_rank • MPI_Send • MPI_Receive • MPI_Broadcast • MPI_Scatter • MPI_Reduce • MPI_Gather • MPI datatypes • MPI_CHAR • MPI_INT • MPI_FLOAT • MPI_DOUBLE
MPI • MPI • Message-passing interface • LAM • MPICH2
MPI Functions • MPI_Init(&argc, &argv) • 프로그램 실행 인수들과 함께mpi함수들을 초기화 해준다. • MPI_Finalize() • mpi함수들을 종료한다. 모든mpi함수들은MPI_Inti() 과MPI_Finalize() 사이에서 호출되어야 한다. • intMPI_Comm_rank(MPI_Commcomm, int *rank) • comm커뮤니케이터에서 자신의 프로세스 id를 얻는다. • intMPI_Comm_size(MPI_Commcomm, int *size) • comm커뮤니케이터에서 실행되는 프로세스의 개수를 얻는다
MPI Functions • intMPI_Send(void *message, int count, MPI_Datatupedatatype, intdest, int tag, MPI_Commcomm) • dest로 메시지를 보낸다. 아래는 각 변수들의 설명이다. message는 보내고자 하는 메시지를 저장하고 있는 버퍼 count 는 보낼 메시지 개수datatype는 보낼 메시지 타입dest는 보내고자 하는 프로세스 id tag는 보내는 메시지에 대한 꼬리표comm은dest와 자신의 프로세스가 속해있는 커뮤니케이터 • intMPI_Recv(void *message, int count, MPI_Datatypedatatype, int source, int tag, MPI_Commcomm, MPI_Status *status) • source로부터 메시지를 받는다. 아래는 각 변수들의 설명이다. message는 받은 메시지를 저장할 버퍼 count는 받을 메시지 개수(받는 메시지 개수보다 작으면 에러 발생)datatype은 받을 메시지 타입 source는 메시지를 보내주는 프로세스 id tag는 받은 메시지를 확인하기 위한 꼬리표(MPI_Recv에서의 tag와MPI_Send에서의 tag가 같아야 한다)comm은 source와 자신의 프로세스가 속해있는 커뮤니케이터 status는 실제받은 데이터에 대한 정보(source와 tag)
MPI Functions • Collective Communication을 위한 함수 • Communicator란 병렬 실행의 대상이 되는 프로세스 그룹으로서 정의된다. 기본적으로 MPI프로그램에서는 MPI_COMM_WORLD라는 기본 Communicator가 생성되는데 이는 동시에 수행되는 모든 병렬 프로세스를 포함한다. 그러나 사용자는 필요에 따라 임의의 프로세스로 구성된 새로운 Communicator를 생성할 수 있기도 하다. 이러한 Communicator에서 정의되는 프로세스간의 통신을 위한 함수들을 다음에 보였다. • intMPI_Bcast(void *message, int count, MPI_Datatypedatatype, int root, MPI_Commcomm) • comm으로 정의된 Communicator에 속한 모든 프로세스들에게 동일한 메시지를 전송한다. root는 메시지를 뿌려주는 프로세스 id. root의 message에만 보내고자 하는 데이터가 들어있고, 다른 프로세스의message는 받은 메시지를 저장할 공간이다. • intMPI_Reduce(void *operand, void *result, int count, MPI_Datatypedatatype, MPI_Opop, int root, MPI_Commcomm) • 모든 프로세스들이MPI_Reduce를 수행하면 모든 operand가 op에 따라 연산을 수행하고 그 결과가 root 프로세스의 result에 저장된다. operand는 연산이 적용될 피연산자 result는 연산결과가 저장될 버퍼 op는 어떤 종료의 연산이 수행될 것인지를 알려주는 OP-CODE root는 연산결과가 저장될 프로세스id • intMPI_Barrier(MPI_Commcomm) • comm Communicator에 속한 모든 프로세스들이MPI_Barrier를 호출할때까지 block시킴으로서 동기화를 시킨다.
MPI Functions • Collective Communication을 위한 함수 • intMPI_Gather(void *send_buf, intsend_count, MPI_Datatypesend_type, void *recv_buf, intrecv_count, MPI_Datatyperecv_type, int root, MPI_commcomm) • root프로세스는 각 프로세스들이 보내준 자료(send_buf)를 프로세스 id 순으로 root의recv_buf에 차곡차곡 쌓는다. • intMPI_Scatter(void *send_buf, intsend_count, MPI_Datatype send _type, void *recv_buf, intrecv_count, MPI_Datatyprecv_type, introot,MPI_Commcomm) • send_buf의 내용을send_count의 크기로 잘라서 모든 프로세스들의recv_buf로 순서대로 전송한다. MPI_Gather와는 반대의 역할 • intMPI_Allgather(void *send_buf, intsend_count, MPI_Dataltypesend_type, void *recv_buf, intrecv_count, MPI_Datatyperecv_type, MPI_commcomm) • MPI_gather와 마찬가지로 모든 프로세스의send_buf의 내용을 모으나, 모든 프로세스의recv_buf에 저장하는 것이 다르다. • intMPI_Allreduce(void *operand, void *result, int count, MPI_Datatypedatatype, MPI_Op, MPI_Commcomm) • MPI_Reduce와 마찬가지로 모든 프로세스의 operand에 op연산을 적용하지만 그 결과를 모든 프로세스의 result가 가지게 된다
MPI Datatypes • Basic datatypes • MPI_CHAR (char) • MPI_INT (int) • MPI_FLOAT (float) • MPI_DOUBLE (double)
MPI Programming Examples #include <mpi.h> #define WORKTAG 1 #define DIETAG 2 /* Local functions */ static void master(void); static void slave(void); static unit_of_work_tget_next_work_item(void); static void process_results(unit_result_t result); static unit_result_tdo_work(unit_of_work_t work); int main(intargc, char **argv) { intmyrank; /* Initialize MPI */ MPI_Init(&argc, &argv); /* Find out my identity in the default communicator */ MPI_Comm_rank(MPI_COMM_WORLD, &myrank); if (myrank == 0) { master(); } else{ slave(); } /* Shut down MPI */ MPI_Finalize(); return 0; }
MPI Programming Examples • /* Get the next unit of work to be done */ • work = get_next_work_item(); • } • /* There's no more work to be done, so receive all the outstanding results from the slaves. */ • for (rank = 1; rank < ntasks; ++rank) { • MPI_Recv(&result, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); • } • /* Tell all the slaves to exit by sending an empty message with the DIETAG. */ • for (rank = 1; rank < ntasks; ++rank) { • MPI_Send(0, 0, MPI_INT, rank, DIETAG, MPI_COMM_WORLD); • } • } • static void slave(void) • { • unit_of_work_t work; • unit_result_t results; • MPI_Status status; • while (1) { • /* Receive a message from the master */ • MPI_Recv(&work, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); • /* Check the tag of the received message. */ • if (status.MPI_TAG == DIETAG) { return; } • /* Do the work */ • result = do_work(work); • /* Send the result back */ • MPI_Send(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); • } • } static void master(void) { intntasks, rank; unit_of_work_t work; unit_result_t result; MPI_Status status; /* Find out how many processes there are in the default communicator */ MPI_Comm_size(MPI_COMM_WORLD, &ntasks); /* Seed the slaves; send one unit of work to each slave. */ for (rank = 1; rank < ntasks; ++rank) { /* Find the next item of work to do */ work = get_next_work_item(); /* Send it to each rank */ MPI_Send(&work, /* message buffer */ 1, /* one data item */ MPI_INT, /* data item is an integer */ rank, /* destination process rank */ WORKTAG, /* user chosen message tag */ MPI_COMM_WORLD); /* default communicator */ } /* Loop over getting new work requests until there is no more work to be done */ work = get_next_work_item(); while (work != NULL) { /* Receive results from a slave */ MPI_Recv(&result, /* message buffer */ 1, /* one data item */ MPI_DOUBLE, /* of type double real */ MPI_ANY_SOURCE, /* receive from any sender */ MPI_ANY_TAG, /* any type of message */ MPI_COMM_WORLD, /* default communicator */ &status); /* info about the received message */ /* Send the slave a new work unit */ MPI_Send(&work, /* message buffer */ 1, /* one data item */ MPI_INT, /* data item is an integer */ status.MPI_SOURCE, /* to who we just received from */ WORKTAG, /* user chosen message tag */ MPI_COMM_WORLD); /* default communicator */
MPI Programming Examples static unit_of_work_tget_next_work_item(void) { /* Fill in with whatever is relevant to obtain a new unit of work suitable to be given to a slave. */ } static void process_results(unit_result_t result) { /* Fill in with whatever is relevant to process the results returned by the slave */ } static unit_result_tdo_work(unit_of_work_t work) { /* Fill in with whatever is necessary to process the work and generate a result */ }