【MPI】實現進程間環形通訊

1. 問題描述

創建np個進程,使第iam個進程向iam+1個進程發送消息,第np-1個進程向第0個進程發送消息,行成一個環形結構

2. 解決思路

申明一個子程序

/************************************************* 
Function:       ring
Description:    實現進程間環形通訊 
Input:          m: 發送的消息
                comm:MPI通訊域
                np: 進程數
                iam:當前進程號 
Output:         n:接收的消息
Return:         void
*************************************************/  
void ring(int m, int *n, MPI_Comm comm, int np, int iam);

2.1 定位前後進程

已知第iam個進程,定位前一個進程。爲了防止第0個進程減1後得到負數,需要加上np

front = (np + iam - 1) % np;

已知第iam個進程,定位下一個進程,爲了使第np-1個進程的下一個進程爲0,需要取模

next = (iam + 1) % np;

2.2 消息發送

思路一

使用MPI_SendMPI_Recv。這對函數是阻塞式操作,爲了防止死鎖,需要有進程先發送消息。最直觀的思路是0號進程先發送再接收,其他進程先接收再發送。但這樣幾乎沒有並行性,效率太低;考慮讓偶數號進程先發送,奇數號進程先接收

if (iam % 2 == 0){ // 讓做一半進程先發送,一半進程再接收
		MPI_Send(&m, 1, MPI_INT, next, 1, comm);
		MPI_Recv(n, 1, MPI_INT, front, 1, comm, &status);
	}
	else{ //一定要有進程在發送之前要先接收偶數進程的消息
		MPI_Recv(n, 1, MPI_INT, front, 1, comm, &status);
		MPI_Send(&m, 1, MPI_INT, next, 1, comm);
	}

思路二

使用MPI_IsendMPI_Irecv。這對函數是非阻塞式操作,因此不會出現死鎖,但是可能有的進程消息還沒有收到就直接退出的情況,因此需要使用MPI_Wait同步進程。

同步的思路很靈活,既可以等待發送和接收都完成,也可以只等待接收操作完成

MPI_Status status[2];
MPI_Request reqs[2];
MPI_Isend(&m, 1, MPI_INT, next, 1, comm, &reqs[0]);
MPI_Irecv(n, 1, MPI_INT, front, 1, comm, &reqs[1]);
//MPI_Waitall(2, reqs, status); // 等待發送和接收都完成
MPI_Wait(&reqs[1], &status[1]); // 僅等待接收完成

思路三

使用MPI_Sendrecv,該函數整合sendrecv操作,認爲sendrecv操作組合是阻塞的,而sendrecv之間又是沒有順序的

MPI_Sendrecv(&m, 1, MPI_INT, next, 1, \
		n, 1, MPI_INT, front, 1, comm, &status);

2.3 主程序

int main(int argc, char *argv[])
{
	// my begin
	int rank;
	int numtasks;

	MPI_Init(&argc, &argv); /*Initializes MPI calls*/
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);     /* obtains the rank of current MPI process */
	MPI_Comm_size(MPI_COMM_WORLD, &numtasks); /* obtains the total number of MPI processes */

	// my function
	int m = rank, n = 100; //m:發送數據,n:接收數據
	ring(m, &n, MPI_COMM_WORLD, numtasks, rank);
	cout << "My rank:" << rank << "\tMy n:" << n;

	// my end
	MPI_Finalize();        /*Finalizes MPI calls */
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章