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
最後に、テストの例を添付します.
出力結果は次のとおりです.
ブロッキング関数
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