1. Collective Communications
개요
Special feature
2. 종류
Broadcast
Scatter
Gather
Allgather
Alltoall
Reduce
Allreduce
1. MPI_Bcast
broadcast
blocking broadcasting
int MPI_Bcast( void* buffer, int count,
MPI_Datatype datatype, int root, MPI_Comm comm )
non-blocking broadcasting
int MPI_Ibcast( void* buffer, int count, MPI_Datatype datatype,
int root, MPI_Comm comm, MPI_Request *request )
2. Example (MPI_Bcast)
C code
#include "stdio.h"
#include <mpi.h>
int main()
{
int i, nrank,nprocs, ROOT=0;
int buf[4]={0,}, buf2[4]={0,};
MPI_Request req;
MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&nrank);
MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
if(nrank==ROOT) buf[0]=5, buf[1]=6, buf[2]=7, buf[3]=8;
if(nrank==nprocs-1) buf2[0]=50, buf2[1]=60, buf2[2]=70, buf2[3]=80;
printf("rank=%d, Before(buf): %d %d %d %d\n",nrank, buf[0],buf[1],buf[2],buf[3]);
MPI_Ibcast(buf2,4,MPI_INT,nprocs-1,MPI_COMM_WORLD,&req);
MPI_Bcast(buf,4,MPI_INT, ROOT,MPI_COMM_WORLD);
printf("rank=%d, After(buf): %d %d %d %d\n",nrank,buf[0],buf[1],buf[2],buf[3]);
MPI_Wait(&req,MPI_STATUS_IGNORE);
printf("rank=%d, AFTER(BUF2): %d %d %d %d\n",nrank, buf2[0],buf2[1],buf2[2],buf2[3]);
MPI_Finalize();
return 0;
}
Result
MPI_Ibcast()
은 호출 후 즉시 return 되기 때문에 MPI_Bcast()
가 바로 시작됨MPI_Bcast()
의 전송이 끝난 이후, MPI_Wait()
에서 MPI_Ibcast()
의 broadcast가 끝날 때 까지 기다림3. MPI_Gather
개요
gather
int MPI_Gather( const void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm )
recvcount
는 전체 data의 개수가 아니라 각 랭크에서 root
로 보내는 개별 data의 개수sendcount
와 recvcount
는 보통 같은 수로 맞춤MPI_Igather()
은 non-blocking gather 함수로, 마지막에 request argument만 추가주의
MPI_Gather()
는 동일한 size의 data만 취합 가능MPI_Gatherv()
사용4. Example (MPI_Gather)
#include <stdio.h>
#include "mpi.h" int main()
{
int isend,irecv[4]={0,},nprocs,nrank;
MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&nrank);
MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
isend=nrank+1;
printf("rank: %d, isend:%d\n",nrank,isend);
MPI_Gather(&isend,1,MPI_INT,irecv,1,MPI_INT,0,MPI_COMM_WORLD);
if(nrank==0) printf("rank:%d irecv=%d %d %d %d\n",nrank,irecv[0],irecv[1],irecv[2],irecv[3]);
MPI_Finalize();
return 0;
}
Result
isend=irank+1
을 rank0(root)로 MPI_Gather()
을 이용하여 취합1. MPI_Gatherv
gatherv
MPI_Gather()
와 동일하나, 각 프로세스로부터의 데이터의 개수가 일정하지 않음MPI_Gatherv()
int MPI_Gatherv( const void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype,
int root, MPI_Comm comm )
2. Example(MPI_Gatherv)
C code
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
int main()
{
int i,myrank;
int isend[3], *irecv;
// ircnt, idisp hard coding
int iscnt, ircnt[3]={1,2,3}, idisp[3]={0,1,3};
MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
// recvbuf에 memory 할당
if(myrank==0) irecv=(int*)malloc(6*sizeof(int));
// 한번에 모든 renk의 값을 초기화
for(i=0;i<myrank+1;i++) isend[i]=myrank+1;
// rank+1 개의 data를 각각 전송
iscnt=myrank+1;
MPI_Gatherv(isend, iscnt,MPI_INT, irecv, ircnt,idisp,MPI_INT,0, MPI_COMM_WORLD);
if(myrank==0){
printf("irecv="); for(i=0;i<6;i++) printf(" %d", irecv[i]);
printf("\n");
}
if(myrank==0) free(irecv);
MPI_Finalize();
return 0;
}
Result
3. allgather/ allgatherv
allgather
int MPI_Allgather( const void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm )
MPI_Gather()
와 동일MPI_Gather()
의 argument 중 root만 빠진 형태MPI_Gather()
+ MPI_Bcast()
allgatherv
int MPI_Allgatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm )
MPI_Gatherv()
와 동일MPI_Allgather()
의 argument 중 root만 빠진 형태MPI_Gatherv()
+ MPI_Bcast()