MPI 阻塞发送和接收是如何工作的?
How does MPI blocking send and receive work?
我正在阅读有关 MPI 阻塞发送和接收的内容,但有些事情我不确定。
在做一些研究时,我发现 MPI 阻塞发送和接收example(第 6-7 页)
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#define MASTER 0
int main (int argc, char *argv[])
{
int numtasks, taskid, len, partner, message;
char hostname[MPI_MAX_PROCESSOR_NAME];
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
/* need an even number of tasks */
if (numtasks % 2 != 0) {
if (taskid == MASTER)
printf("Quitting. Need an even number of tasks: numtasks=%d\n", numtasks);
} else {
if (taskid == MASTER)
printf("MASTER: Number of MPI tasks is: %d\n",numtasks);
MPI_Get_processor_name(hostname, &len);
printf ("Hello from task %d on %s!\n", taskid, hostname);
/* determine partner and then send/receive with partner */
if (taskid < numtasks/2) {
partner = numtasks/2 + taskid;
MPI_Send(&taskid, 1, MPI_INT, partner, 1, MPI_COMM_WORLD);
MPI_Recv(&message, 1, MPI_INT, partner, 1, MPI_COMM_WORLD, &status);
} else if (taskid >= numtasks/2) {
partner = taskid - numtasks/2;
MPI_Recv(&message, 1, MPI_INT, partner, 1, MPI_COMM_WORLD, &status);
MPI_Send(&taskid, 1, MPI_INT, partner, 1, MPI_COMM_WORLD);
}
/* print partner info and exit*/
printf("Task %d is partner with %d\n",taskid,message);
}
MPI_Finalize();
}
我想知道的事情:
- 一半的进程在接收之前发送,为什么会这样?
- 如果在接收之前全部发送,会发生什么情况?
如果所有 MPI 任务 MPI_Send()
然后 MPI_Recv()
,那么它不符合 MPI 标准。
原因是 MPI_Send()
可能会阻塞,直到发布收到的匹配为止,在您的情况下,这将意味着死锁。
为了避免死锁,从而写出正确的程序,有几种选择:
- 顺序发送和接收(例如一半发送然后接收,另一半接收然后发送)
- 使用非阻塞接收(例如所有 MPI 任务
MPI_Irecv()
,然后是 MPI_Send()
,最后是 MPI_Wait()
- 使用
MPI_Sendrecv()
,这是最合适的,因为您的程序在两个任务之间交换数据。
我正在阅读有关 MPI 阻塞发送和接收的内容,但有些事情我不确定。
在做一些研究时,我发现 MPI 阻塞发送和接收example(第 6-7 页)
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#define MASTER 0
int main (int argc, char *argv[])
{
int numtasks, taskid, len, partner, message;
char hostname[MPI_MAX_PROCESSOR_NAME];
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
/* need an even number of tasks */
if (numtasks % 2 != 0) {
if (taskid == MASTER)
printf("Quitting. Need an even number of tasks: numtasks=%d\n", numtasks);
} else {
if (taskid == MASTER)
printf("MASTER: Number of MPI tasks is: %d\n",numtasks);
MPI_Get_processor_name(hostname, &len);
printf ("Hello from task %d on %s!\n", taskid, hostname);
/* determine partner and then send/receive with partner */
if (taskid < numtasks/2) {
partner = numtasks/2 + taskid;
MPI_Send(&taskid, 1, MPI_INT, partner, 1, MPI_COMM_WORLD);
MPI_Recv(&message, 1, MPI_INT, partner, 1, MPI_COMM_WORLD, &status);
} else if (taskid >= numtasks/2) {
partner = taskid - numtasks/2;
MPI_Recv(&message, 1, MPI_INT, partner, 1, MPI_COMM_WORLD, &status);
MPI_Send(&taskid, 1, MPI_INT, partner, 1, MPI_COMM_WORLD);
}
/* print partner info and exit*/
printf("Task %d is partner with %d\n",taskid,message);
}
MPI_Finalize();
}
我想知道的事情:
- 一半的进程在接收之前发送,为什么会这样?
- 如果在接收之前全部发送,会发生什么情况?
如果所有 MPI 任务 MPI_Send()
然后 MPI_Recv()
,那么它不符合 MPI 标准。
原因是 MPI_Send()
可能会阻塞,直到发布收到的匹配为止,在您的情况下,这将意味着死锁。
为了避免死锁,从而写出正确的程序,有几种选择:
- 顺序发送和接收(例如一半发送然后接收,另一半接收然后发送)
- 使用非阻塞接收(例如所有 MPI 任务
MPI_Irecv()
,然后是MPI_Send()
,最后是MPI_Wait()
- 使用
MPI_Sendrecv()
,这是最合适的,因为您的程序在两个任务之间交换数据。