1対1通信

MPIには大きく分けて

  • 1対1通信
  • 集団通信

というものがあります。今回は1対1通信について話をします。
1対1通信はその名の通り、PCとPCの間で簡単な通信をするときに使用します。早速やってみましょう。

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

int main(int argc,char *argv[])
{
        int rank,size;
        MPI_Init(&argc,&argv);
        MPI_Comm_rank(MPI_COMM_WORLD,&rank);
        MPI_Comm_size(MPI_COMM_WORLD,&size);
        printf("hello world I'm %d of %d my number is %d\n",rank,size,mynum);
        MPI_Finalize();
        return 0;
}

ここで、

  • 0番PCで乱数を生成
  • 乱数を0番から1番に送信
  • 確認

ということをしてみます。
まずは、乱数の動作確認です。
こんな感じ

#include<stdio.h>
#include"mpi.h"
#include<stdlib.h>
#include<time.h>
#define N 10000000

int main(int argc,char *argv[])
{
        int rank,size;
        int mynum;★★★
        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\n",rank,size,mynum);★★★
        MPI_Finalize();
        return 0;
}

実行すると…、

$ mpicc -o 004-2 004-2.c 
$ mpirun --machinefile ../machinefile ./004-2
hello world I'm 0 of 3 my number is 1031619866
hello world I'm 1 of 3 my number is 731063600
hello world I'm 2 of 3 my number is 428163429

こんな結果になります(数字は乱数なので結果が違っているはずです)。
では、実際に転送するための関数を埋め込みましょう今回は0番のPCから1番のPCに向かって取得した乱数を転送します。
こんな感じ、

#include<stdio.h>
#include"mpi.h"
#include<stdlib.h>
#include<unistd.h>
#include<time.h>
#define N 10000000

int main(int argc,char *argv[])
{
        int rank,size;
        int mynum;
        int myerr=0;★★★
        int yournum=0;★★★
        MPI_Status status;★★★
        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(10);★★★
        if(rank == 0)★★★
                myerr = MPI_Send(&mynum,1,MPI_INT,1,1,MPI_COMM_WORLD);★★★
        if(rank == 1)★★★
                myerr = MPI_Recv(&yournum,1,MPI_INT,0,1,MPI_COMM_WORLD,&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;
}
$ mpirun --machinefile ../machinefile ./004-3
hello world I'm 0 of 3 my number is 2280995 your number is 0
hello world I'm 1 of 3 my number is 1841806718 your number is 0
hello world I'm 2 of 3 my number is 474026168 your number is 0
hello world I'm 2 of 3 my number is 474026168 your number is 0(err No. is 0)
hello world I'm 0 of 3 my number is 2280995 your number is 0(err No. is 0)
hello world I'm 1 of 3 my number is 1841806718 your number is 2280995(err No. is 0)

きちんと0番から1番にメッセージが送られていることを確認できました。

では応用例として、0→1、1→2、2→0と通信してみましょう。

#include<stdio.h>
#include"mpi.h"
#include<stdlib.h>
#include<unistd.h>
#include<time.h>
#define N 10000000

int main(int argc,char *argv[])
{
        int rank,size;
        int mynum;
        int myerr=0;
        int yournum=0;
        MPI_Status status;
        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(10);
        myerr = MPI_Send(&mynum  ,1,MPI_INT,(rank+1)%size,     (rank+1)%size,MPI_COMM_WORLD);★★★
        myerr = MPI_Recv(&yournum,1,MPI_INT,(rank+size-1)%size,rank         ,MPI_COMM_WORLD,&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 004-4 004-4.c 
$ mpirun --machinefile ../machinefile ./004-4
hello world I'm 0 of 3 my number is 1984022592 your number is 0
hello world I'm 1 of 3 my number is 592282443 your number is 0
hello world I'm 2 of 3 my number is 1368506247 your number is 0
hello world I'm 0 of 3 my number is 1984022592 your number is 1368506247(err No. is 0)
hello world I'm 1 of 3 my number is 592282443 your number is 1984022592(err No. is 0)
hello world I'm 2 of 3 my number is 1368506247 your number is 592282443(err No. is 0)

ね、かんたんでしょ?実はこれをもっと簡単に書く方法があります。一行でSend と Recvを実現している関数を使います。

#include<stdio.h>
#include"mpi.h"
#include<stdlib.h>
#include<unistd.h>
#include<time.h>
#define N 10000000

int main(int argc,char *argv[])
{
        int rank,size;
        int mynum;
        int myerr=0;
        int yournum=0;
        MPI_Status status;
        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(10);
        myerr = MPI_Sendrecv(&mynum,1,MPI_INT,(rank+1)%size,(rank+1)%size,&yournum,1,MPI_INT,(rank+size-1)%size,rank,MPI_COMM_WORLD,&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 004-5 004-5.c 
$ mpirun --machinefile ../machinefile ./004-5
hello world I'm 0 of 3 my number is 95868441 your number is 0
hello world I'm 1 of 3 my number is 860512961 your number is 0
hello world I'm 2 of 3 my number is 1637154686 your number is 0
hello world I'm 1 of 3 my number is 860512961 your number is 95868441(err No. is 0)
hello world I'm 2 of 3 my number is 1637154686 your number is 860512961(err No. is 0)
hello world I'm 0 of 3 my number is 95868441 your number is 1637154686(err No. is 0)

今回はこれまで。

戻る