MPI_Send 和 MPI_Recv 不匹配 C
MPI_Send and MPI_Recv not matching C
我想在这里实现一个工作池。我应该向从进程发送 100 个不同的数字。然后每个从属进程 returns 向主进程发送一些东西,另一个不同的数字由主进程发送给从属进程。这一直持续到所有 100 次迭代都结束。
我的程序有点陷入无限循环,我认为这是由于 MPI_Send 和 MPI_Recv 的映射不正确造成的。我不知道我做错了什么。我花了好几个小时研究这个但无济于事。我是 MPI 和一般编程的新手。代码如下:
if(rank == 0) {
int i,iteration = 0, a=0,inside=0,temp=0;
for(i = 1; i < slaves; i++) {
MPI_Send(&iteration,1,MPI_INT,i,0,MPI_COMM_WORLD);
MPI_Send(&a,1,MPI_INT,i,1,MPI_COMM_WORLD);
iteration++;
}
while(iteration < 100+slaves){
MPI_Recv(&temp,1,MPI_INT,MPI_ANY_SOURCE,0, MPI_COMM_WORLD, &status);
if(iteration < 100) {
MPI_Send(&iteration,1,MPI_INT,status.MPI_SOURCE,0,MPI_COMM_WORLD);
MPI_Send(&a,1,MPI_INT,status.MPI_SOURCE,1,MPI_COMM_WORLD);
}
iteration++;
inside = inside + temp;
}
}
else {
int iteration=0,count=0;
if(iteration < 100) {
MPI_Recv(&iteration,1,MPI_INT,0,0,MPI_COMM_WORLD,&status);
MPI_Recv(&count,1,MPI_INT,0,1,MPI_COMM_WORLD,&status);
MPI_Send(&count,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
}
你也需要在你的奴隶队伍中循环。现在,您将 iteration
和 a
从主机发送到从机,将 count
从从机发送回主机,然后主机尝试发送 iteration
和 a
来自 while
循环,而奴隶们愉快地退出了 else
块并继续他们快乐的方式。要么去掉主进程中的 while
循环,这样它就不会发送从属进程永远不会收到的东西,要么在从属进程中添加一个循环,这样它们就能正确地接收数据。
MPI 中最重要的事情之一就是理解,通常每个进程都执行相同的程序。这使 mpi_rank
成为您最好的朋友之一,因为您需要它来区分每个进程必须完成的不同任务。
另一个需要理解的重点是 blocking/non-blocking MPI 中的通信是如何工作的。这里我们使用阻塞通信(MPI_Send()
和 MPI_Recv()
)。这意味着进程将在 MPI_Recv()
之类的函数调用处停止,并等待通信伙伴到达它的 "counterpart"(MPI_Send()
,向我发送内容)。
您的程序卡住这一事实很好地表明没有相同数量的 MPI_Send()
和 MPI_Recv()
调用:某个进程仍在等待接收 message/be能够发送消息。
对于你的例子,我会尝试做这样的事情:
while( iterations < 100 ){
// in general every process has to do something for 100 times,
// but we have to have to distinguish between master and slaves.
if( mpi_rank == 0 ){
// The master process...
for( int slave_rank = 1; slave_rank < mpi_size; slave_rank++ ){
// ... has to send, receive and send once again something to/from every(!) slave, ...
MPI_Send( [one int to slave_rank] );
MPI_Recv( [one int from slave_rank] );
MPI_Send( [another int to slave_rank] );
}
}
else{
//... while the slaves just have to receive, send and receive again from/to one process (the master)
MPI_Recv( [one int from master] );
MPI_Send( [one int to master] );
MPI_Recv( [another int from master] );
}
iterations++;
}
你的任务听起来像:Master 发送 int 给 slave #1, #2, #3.....,然后他从 #1, #2, #3..... 接收,然后他发送另一个int 到#1,#2,#3。您可能会认识到您必须遍历所有从属队列 3 次。
这个解决方案是不同的(虽然结果是一样的),但更短:Master 发送 int 到 slave #1,然后从 slave #1 接收 int,然后发送另一个 int 到 slave #1。之后,对 slave #2、#3、#4 重复同样的事情......这样我们只需要遍历所有 slave ranks 一次。
我想在这里实现一个工作池。我应该向从进程发送 100 个不同的数字。然后每个从属进程 returns 向主进程发送一些东西,另一个不同的数字由主进程发送给从属进程。这一直持续到所有 100 次迭代都结束。
我的程序有点陷入无限循环,我认为这是由于 MPI_Send 和 MPI_Recv 的映射不正确造成的。我不知道我做错了什么。我花了好几个小时研究这个但无济于事。我是 MPI 和一般编程的新手。代码如下:
if(rank == 0) {
int i,iteration = 0, a=0,inside=0,temp=0;
for(i = 1; i < slaves; i++) {
MPI_Send(&iteration,1,MPI_INT,i,0,MPI_COMM_WORLD);
MPI_Send(&a,1,MPI_INT,i,1,MPI_COMM_WORLD);
iteration++;
}
while(iteration < 100+slaves){
MPI_Recv(&temp,1,MPI_INT,MPI_ANY_SOURCE,0, MPI_COMM_WORLD, &status);
if(iteration < 100) {
MPI_Send(&iteration,1,MPI_INT,status.MPI_SOURCE,0,MPI_COMM_WORLD);
MPI_Send(&a,1,MPI_INT,status.MPI_SOURCE,1,MPI_COMM_WORLD);
}
iteration++;
inside = inside + temp;
}
}
else {
int iteration=0,count=0;
if(iteration < 100) {
MPI_Recv(&iteration,1,MPI_INT,0,0,MPI_COMM_WORLD,&status);
MPI_Recv(&count,1,MPI_INT,0,1,MPI_COMM_WORLD,&status);
MPI_Send(&count,1,MPI_INT,0,0,MPI_COMM_WORLD);
}
}
你也需要在你的奴隶队伍中循环。现在,您将 iteration
和 a
从主机发送到从机,将 count
从从机发送回主机,然后主机尝试发送 iteration
和 a
来自 while
循环,而奴隶们愉快地退出了 else
块并继续他们快乐的方式。要么去掉主进程中的 while
循环,这样它就不会发送从属进程永远不会收到的东西,要么在从属进程中添加一个循环,这样它们就能正确地接收数据。
MPI 中最重要的事情之一就是理解,通常每个进程都执行相同的程序。这使 mpi_rank
成为您最好的朋友之一,因为您需要它来区分每个进程必须完成的不同任务。
另一个需要理解的重点是 blocking/non-blocking MPI 中的通信是如何工作的。这里我们使用阻塞通信(MPI_Send()
和 MPI_Recv()
)。这意味着进程将在 MPI_Recv()
之类的函数调用处停止,并等待通信伙伴到达它的 "counterpart"(MPI_Send()
,向我发送内容)。
您的程序卡住这一事实很好地表明没有相同数量的 MPI_Send()
和 MPI_Recv()
调用:某个进程仍在等待接收 message/be能够发送消息。
对于你的例子,我会尝试做这样的事情:
while( iterations < 100 ){
// in general every process has to do something for 100 times,
// but we have to have to distinguish between master and slaves.
if( mpi_rank == 0 ){
// The master process...
for( int slave_rank = 1; slave_rank < mpi_size; slave_rank++ ){
// ... has to send, receive and send once again something to/from every(!) slave, ...
MPI_Send( [one int to slave_rank] );
MPI_Recv( [one int from slave_rank] );
MPI_Send( [another int to slave_rank] );
}
}
else{
//... while the slaves just have to receive, send and receive again from/to one process (the master)
MPI_Recv( [one int from master] );
MPI_Send( [one int to master] );
MPI_Recv( [another int from master] );
}
iterations++;
}
你的任务听起来像:Master 发送 int 给 slave #1, #2, #3.....,然后他从 #1, #2, #3..... 接收,然后他发送另一个int 到#1,#2,#3。您可能会认识到您必须遍历所有从属队列 3 次。
这个解决方案是不同的(虽然结果是一样的),但更短:Master 发送 int 到 slave #1,然后从 slave #1 接收 int,然后发送另一个 int 到 slave #1。之后,对 slave #2、#3、#4 重复同样的事情......这样我们只需要遍历所有 slave ranks 一次。