Yeon's 개발블로그

지식을 전파하는 개발자가 되고싶습니다.

Cloud Computing

8. MPI프로그램 1:1 통신모드 (1:1 Communication Modes)

Dev.yeon 2020. 10. 21. 22:27
Communicattion mode Blocking Routines Nonblocking Routines
Synchronous Send MPI_Ssend MPI_Issend
Standard Send MPI_Send MPI_Isend
Standard Receive MPI_Recv MP_Irecv
  • Blocking routines: 송신하려는 변수나 배열의 데이터가 다른곳에 복사된 직후 종료
  • Nonblocking routines: 송신하겠다는 의사만 수신할 프로세스에게 표시하고 종료
  • Synchronous mode: 상대방의 송신이 끝나야 본인도 종료
  • Standard mode: 상대방과는 상관없이 본인이 실행, 종료

MPI_Isend(buf,count,datatype,dest,tag,comm,request)MPI_Irecv(buf,count,datatype,dest,tag,comm,request)

nonblocking의 경우에는 send와 receive모두 request를 포함하게 된다. request변수를 이용해서 MPI_Wait()또는 MPI_Test()를 실행할 수 있다. MPI_Wait()은 실행이 끝날 때 까지 기다리는 것이고, MPI_Test()는 실행이 끝난 여부에 대한 flag를 반환하게 된다. 

1. one way (send → receive) : 아무 문제도 일어나지 않는다. 

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0)
MPI_Send(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD);
else if(my_rank==1){
MPI_Recv(&b,1,MPI_INT,0,tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
printf("b=%d",b);
}
MPI_Finalize();
}

 

2. one way (Isend→ receive) : 아무 문제도 일어나지 않는다. MPI_Isend와 MPI_Wait 가 MPI_Send의 역할을 한다. 

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1;
MPI_Status status;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0){
MPI_ISend(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req1);
MPI_Wait(&req1,&status);
}
else if(my_rank==1){
MPI_Recv(&b,1,MPI_INT,0,tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
printf("b=%d",b);
}
MPI_Finalize();
}

 

3. one way (send → Ireceive) : 아무 문제도 일어나지 않는다. MPI_Irecv와 MPI_Wait 가 MPI_Recv의 역할을 한다.

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1;
MPI_Status status;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0)
MPI_Send(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD);
else if(my_rank==1){
MPI_IRecv(&b,1,MPI_INT,0,tag,MPI_COMM_WORLD,&req1);
MPI_Wait(&req1,&status);
printf("b=%d",b);
}
MPI_Finalize();
}

 

4. one way (Isend → Ireceive) : 아무 문제도 일어나지 않는다. MPI_Isend와 MPI_Wait 가 MPI_Send의 역할을 하고, MPI_Irecv와 MPI_Wait 가 MPI_Recv의 역할을 한다. 

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1,req2;
MPI_Status status1,status2;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0){
MPI_ISend(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req1);
MPI_Wait(&req1,&status1);
}
else if(my_rank==1){
MPI_IRecv(&b,1,MPI_INT,0,tag,MPI_COMM_WORLD,&req2);
MPI_Wait(&req2,&status2);
printf("b=%d",b);
}
MPI_Finalize();
}

 

5. both way(SR, SR) : size가 클 경우 deadlock 발생. 보내려는 data가 많아 상대 시스템 버퍼에 여유가 없다면 둘다 보내고나서 상대방의 receive를 기다리기때문에 deadlock이 발생할 수도 있다.  

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1,req2;
MPI_Status status1,status2;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0){
MPI_Send(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD);
MPI_Recv(&b,1,MPI_INT,1,tag,MPI_COMM_WORLD,&status);
printf("b=%d",b);
}
else if(my_rank==1){
MPI_Send(&a,1,MPI_INT,0,tag,MPI_COMM_WORLD);
MPI_Recv(&b,1,MPI_INT,0,tag,MPI_COMM_WORLD,&status);
printf("b=%d",b);
}
MPI_Finalize();
}

 

6. both way(ISR, ISR): 아무 문제도 일어나지 않는다. ISR 다음에 바로 receive로 넘어간다음, ISR을 기다리기 때문에 deadlock이 걸리지 않는다. 만약 wait를 ISR다음에 바로 써주게 되면 deadlock의 가능성이 있다. 

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1,req2;
MPI_Status status1,status2;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0){
MPI_ISend(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req1);
MPI_Recv(&b,1,MPI_INT,1,tag,MPI_COMM_WORLD,&status);
MPI_Wait(&req1,&status);
printf("b=%d",b);
}
else if(my_rank==1){
MPI_ISend(&a,1,MPI_INT,0,tag,MPI_COMM_WORLD,&req2);
MPI_Recv(&b,1,MPI_INT,0,tag,MPI_COMM_WORLD,&status);
MPI_Wait(&req2,&status);
printf("b=%d",b);
}
MPI_Finalize();
}

 

7. both way(RS, RS): 프로그램이 실행되지 않는다. 모두 Receive해서 Send를 기다리고 있는 상황이기 때문에 deadlock이 발생한다. 

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1,req2;
MPI_Status status1,status2;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0){
MPI_Recv(&b,1,MPI_INT,1,tag,MPI_COMM_WORLD,&status);
MPI_Send(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD);
printf("b=%d",b);
}
else if(my_rank==1){
MPI_Recv(&b,1,MPI_INT,0,tag,MPI_COMM_WORLD,&status);
MPI_Send(&a,1,MPI_INT,0,tag,MPI_COMM_WORLD);
printf("b=%d",b);
}
MPI_Finalize();
}

 

8. both way(IRS, IRS): 아무 문제도 일어나지 않는다. IRS 다음에 바로 send로 넘어간다음, IRS을 기다리기 때문에 deadlock이 걸리지 않는다.

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1,req2;
MPI_Status status1,status2;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0){
MPI_Irecv(&b,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req1);
MPI_Send(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD);
MPI_Wait(&req1,&status);
printf("b=%d",b);
}
else if(my_rank==1){
MPI_Irecv(&b,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req1);
MPI_Send(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD);
MPI_Wait(&req1,&status);
printf("b=%d",b);
}
MPI_Finalize();
}

 

9. both way (SR , RS): 아무 문제도 일어나지 않는다. 

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1,req2;
MPI_Status status1,status2;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0){
MPI_Send(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD);
MPI_Recv(&b,1,MPI_INT,1,tag,MPI_COMM_WORLD,&status);
printf("b=%d",b);
}
else if(my_rank==1){
MPI_Recv(&b,1,MPI_INT,0,tag,MPI_COMM_WORLD,&status);
MPI_Send(&a,1,MPI_INT,0,tag,MPI_COMM_WORLD);
printf("b=%d",b);
}
MPI_Finalize();
}

 

10. both way(ISIR, ISIR) : 아무 문제도 일어나지 않는다. 

#include<stdio.h>
#include<mpi.h>

void main(){
int myrank,size;
int a=10,b,tag=5;
MPI_Request req1,req2;
MPI_Status status1,status2;

MPI_Init(NULL,NULL);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);

if(my_rank==0){
MPI_ISend(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req1);
MPI_IRecv(&b,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req2);
}
else if(my_rank==1){
MPI_ISend(&a,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req1);
MPI_IRecv(&b,1,MPI_INT,1,tag,MPI_COMM_WORLD,&req2);
}
MPI_Wait(&req1,&status);
MPI_Wait(&req2,&status);
printf("b=%d",b);
MPI_Finalize();
}​

 

* MPI_Sendrecv(send_buf,send_count, send_type,dest,send_tag, recv_buf,recv_count,recv_type,src,recv_tag,MPI_COMM_WORLD,MPI_STATUS);