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);
'Cloud Computing' 카테고리의 다른 글
10. 병렬프로그래밍: 병렬화가 잘되는 경우 (Embarrassingly Parallel Computations) (0) | 2020.10.22 |
---|---|
9. MPI프로그램 집합통신 (Collective Communication) (0) | 2020.10.21 |
7. MPI 프로그램 기본예제(Send, Receive) (8) | 2020.10.21 |
6. MPI program: Coding, Compile, and Run (0) | 2020.10.21 |
5. 병렬 프로그램의 성능 평가 (Performance) (0) | 2020.10.21 |