MPI学習ノート——ポイント対ポイント通信


1対のプロセス間のデータ変換、すなわちデータを送信しながらデータを受信し、ポイントツーポイント通信はMPI通信メカニズムの基礎であり、同期通信と非同期通信の2つのメカニズムに分けられる.
ブロッキング関数
1.       int MPI_send(void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm)
IN bufが送信するメッセージデータのヘッダアドレス
IN count送信メッセージ配列要素の個数
IN datatype送信メッセージのデータ型
IN dest受信メッセージのプロセス番号
IN tagメッセージラベル
IN comm通信子
2.       int MPI_Recv(void *buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Status *status)
OUT buf受信メッセージデータのヘッダアドレス
IN Count受信メッセージ配列要素の最大個数
IN datatype受信メッセージのデータ型
INソース送信メッセージのプロセス番号
IN tagメッセージラベル
IN comm通信子
OUT statusメッセージ受信時に返される状態
3.       int MPI_Get_Count(MPI_Status status,MPI_Datatype datatype,int *count)
IN statusメッセージ受信時に返される状態
IN datatypeメッセージ受信時に返されるタイプ
OUT Countメッセージ受信時の配列要素の個数
4.       int MPI_Sendrecv(void *sendbuf,int sendcount,MPI_Datatype sendtype,int dest,int sendtag,void *recvbuf,int recvcount,MPI_Datatype recvtype,int source,int recvtag,MPI_Comm comm,MPI_Status *status)
IN sendbufが送信するメッセージデータのヘッダアドレス
IN sendcount送信メッセージ配列要素の個数
IN sendtype送信メッセージのデータ型
IN dest受信メッセージのプロセス番号
IN sendtagメッセージラベル送信
OUT recvbuf受信メッセージデータのヘッダアドレス
IN recvcount受信メッセージ配列要素の最大数
IN recvtype受信メッセージのデータ型
IN Source送信メッセージのプロセス番号
IN recvtag受信メッセージラベル
IN comm通信子
OUT statusメッセージ受信時に返される状態
5.       int MPI_Sendrecv_replace(void *sendbuf,int count,MPI_Datatype datatype,int dest,int sendtag,int source,int recving,MPI_Comm comm,MPI_Status *status)
OUT bufメッセージデータの送受信の先頭アドレス
IN Count送受信メッセージ配列要素の個数
IN dest受信メッセージのプロセス番号
IN sendtagメッセージラベル送信
INソース送信メッセージのプロセス番号
IN recvtag受信メッセージラベル
IN comm通信子
OUT statusメッセージ受信時に返される状態
6.       int MPI_probe(int source,int tag,MPI_Comm comm,MPI_Status *status)
IN source送信メッセージプロセスの番号
IN tag受信メッセージのラベル
IN comm通信子
OUT statusはメッセージの状態に戻ります
7.       int MPI_Iprobe(int source,int tag,MPI_Comm comm,int *flag,MPI_Status *status)
IN source送信メッセージプロセスの番号
IN tag受信メッセージのラベル
IN comm通信子
OUT flag指定メッセージが到着した場合、flag戻り値はtrue
OUT statusは到着メッセージの状態を返す
ノンブロッキング関数
非ブロック通信関数とは、通信中に通信終了を待たずに戻ることを意味し、通常、このような通信過程はコンピュータのバックグラウンドに渡され、コンピュータシステムが非ブロック通信関数をサポートするハードウェアを提供すれば、計算と通信を時間的にオーバーラップさせ、並列計算の効率を高めることができる.
1.       int MPI_Isend(void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,MPI_Request *request)
IN bufが送信するメッセージデータのヘッダアドレス
IN count送信メッセージ配列要素の個数
IN datatype送信メッセージのデータ型
IN dest受信メッセージのプロセス番号
IN tagメッセージラベル
IN comm通信子
OUT request要求ハンドル1杯将来照会
2.       int MPI_Irecv(void *buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Request *request)
OUT buf受信メッセージデータのヘッダアドレス
IN Count受信メッセージ配列要素の個数
IN datatype受信メッセージのデータ型
INソース送信メッセージのプロセス番号
IN tagメッセージラベル
IN comm通信子
OUT requestリクエストハンドル以北将来クエリー
MPI_IsendとMPI_Irecvは、メッセージの送信または受信の完了を待つことなく、他のタスクを実行できます.
3.       Int MPI_wait(MPI_Request *request,MPI_Status *status)
INOUTリクエストハンドル
OUT statusがメッセージを送信または受信した状態
requestが示す操作が完了した場合、MPI_Waitは待機状態を終了します
4.       Int MPI_Test(MPI_Request *request,int *flag,MPI_Status *status)
INOUTリクエストハンドル
OUT flag requestで指す操作が完了した戻り値はtrue
OUT statusがメッセージを送信または受信した状態
5.       Int MPI_Request_free(MPI_Request *request)
INOUT request要求ハンドル、戻り値MPI_Request_null
単一リクエストのクエリー
6.       Int MPI_Waitany(int count,MPI_Request *array_of_requests,int *index,MPI_Status *status)
IN count要求ハンドルの個数
INOUT   array_of_requestsリクエストハンドル配列
OUT indexが通信操作を完了したハンドル指標
OUT statusメッセージの状態
すべての要求ハンドルのうち少なくとも1つが通信動作を完了している場合には戻り、1つ以上の要求ハンドルが完了している場合にはMPI_waitanyはランダムにそのうちの1つを選択し、すぐに戻ります.
7.       Int MPI_Testany(int Count,MPI_Request *array)
IN count要求ハンドル個数
INOUT   array_of_requestsリクエストハンドル配列
OUT indexが通信操作を完了したハンドル指標
OUT flagが完了している場合はflag=true
OUT statusメッセージの状態
通信操作が完了したかどうかにかかわらず、すぐに戻ります.
8.       Int MPI_Waitall(int Count,MPI_Request *array_of_requests)
IN count要求ハンドルの個数
INOUT   array_of_requestsリクエストハンドル配列
INOUT   array_of_statusのすべてのメッセージのステータス配列
すべての通信操作が完了してから戻ります.そうしないと、待機します.
9.       Int MPI_Testall(int Count,MPI_Request *array_of_requests,int *flag,MPI_Status *array_of_status)
IN count要求ハンドルの個数
INOUT   array_of_requestsリクエストハンドル配列
OUT flagが1つ完成していない場合flag=false
INOUT   array_of_statusのすべてのメッセージのステータス配列
すべての通信操作が完了したかどうかにかかわらず、すぐに戻ります.
10.   Int MPI_Cancel(MPI_Request *request)
INOUTリクエストハンドル
送信または受信操作をキャンセル
11.   Int MPI_Test_cancelled(MPI_Status *status,int *flag)
IN statusメッセージの状態
OUT flagキャンセル済みの場合flag=true
最後に、テストの例を添付します.
#include "mpi.h"
#include <stdio.h>
#include <math.h>
#include <malloc.h>


void main(int argc,char **argv){
	int rank,bsize,*buf,recv;
	MPI_Comm comm=MPI_COMM_WORLD;
	MPI_Status status;
	int nums[4]={0,1,2,3};
	MPI_Init(&argc,&argv);
	MPI_Comm_rank(comm,&rank);
	if(rank==0){
		MPI_Send(&nums[rank],1,MPI_INT,4,0,comm);
	}
	else if(rank==1){
		MPI_Pack_size(1,MPI_INT,comm,&bsize);
		bsize+=2*MPI_BSEND_OVERHEAD;
		buf=(int *)malloc(bsize);
		MPI_Buffer_attach(buf,bsize+MPI_BSEND_OVERHEAD);
		MPI_Bsend(&nums[rank],1,MPI_INT,5,0,comm);
		MPI_Buffer_detach(&buf,&bsize);
		free(buf);
	}else if(rank==2){
		MPI_Rsend(&nums[rank],1,MPI_INT,6,0,comm);
	}else if(rank==3){
		MPI_Ssend(&nums[rank],1,MPI_INT,7,0,comm);
	}else if(rank==4){
		MPI_Recv(&recv,1,MPI_INT,0,0,comm,&status);
		printf("Process %d Recv Mes from process %d: %d
",rank,status.MPI_SOURCE,recv); }else if(rank==5){ MPI_Recv(&recv,1,MPI_INT,1,0,comm,&status); printf("Process %d Recv Mes from process %d: %d
",rank,status.MPI_SOURCE,recv); }else if(rank==6){ MPI_Recv(&recv,1,MPI_INT,2,0,comm,&status); printf("Process %d Recv Mes from process %d: %d
",rank,status.MPI_SOURCE,recv); }else if(rank==7){ MPI_Recv(&recv,1,MPI_INT,3,0,comm,&status); printf("Process %d Recv Mes from process %d: %d
",rank,status.MPI_SOURCE,recv); } MPI_Finalize(); }

出力結果は次のとおりです.
Process 4 Recv Mes from process 0: 0
Process 6 Recv Mes from process 2: 2
Process 5 Recv Mes from process 1: 1
Process 7 Recv Mes from process 3: 3