今迄やっていたのは、同期通信と言って例えば
sendしたらrecvが終わるまで自動的に待ちます。これが効率的なときと効率的でない時があります。
この非効率な時は非同期通信を検討します。非同期通信は以下のようにします。
#include<stdio.h>
#include"mpi.h"
#include<stdlib.h>
#include<unistd.h>
#include<time.h>
int main(int argc,char *argv[])
{
int rank,size;
int mynum;
int myerr=0;
int yournum=0;
MPI_Status status;
MPI_Request request;★★★
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
srand(time(NULL)+rank);
mynum = rand();
printf("hello world I'm %d of %d my number is %d your number is %d\n",rank,size,mynum,yournum);
sleep(3);
if( rank == 0 )★★★
myerr = MPI_Isend(&mynum ,1,MPI_INT,1,1,MPI_COMM_WORLD,&request);★★★
if( rank == 1 )★★★
myerr = MPI_Irecv(&yournum,1,MPI_INT,0,1,MPI_COMM_WORLD,&request);★★★
printf("hello world I'm %d of %d my number is %d your number is %d(err No. is %d)\n",rank,size,mynum,yournum,myerr);★★★
sleep(3);
if( rank == 0 || rank == 1 )★★★
myerr = MPI_Wait(&request,&status);★★★
printf("hello world I'm %d of %d my number is %d your number is %d(err No. is %d)\n",rank,size,mynum,yournum,myerr);
MPI_Finalize();
return 0;
}
実行するとこんな感じ
$ mpicc -o 006-1 006-1.c
$ mpirun --machinefile ../machinefile ./006-1
hello world I'm 0 of 3 my number is 618743022 your number is 0
hello world I'm 1 of 3 my number is 1376539288 your number is 0
hello world I'm 2 of 3 my number is 9998132 your number is 0
hello world I'm 1 of 3 my number is 1376539288 your number is 0(err No. is 0)
hello world I'm 2 of 3 my number is 9998132 your number is 0(err No. is 0)
hello world I'm 0 of 3 my number is 618743022 your number is 0(err No. is 0)
hello world I'm 0 of 3 my number is 618743022 your number is 0(err No. is 0)
hello world I'm 2 of 3 my number is 9998132 your number is 0(err No. is 0)
hello world I'm 1 of 3 my number is 1376539288 your number is 618743022(err No. is 0)
この処理はMPI_Wait()が終わるまでに別の処理ができます。これを活かせる方法として
- 変数Aを送信している間に
- 変数Bの処理をする
- 変数Aの送信を終える
という通信と計算をオーバーラップさせることで並列化に必要な通信を隠蔽することができます。
今回はここまでです。