一个简单的MPI程序
如果有人告诉我,当n=40(第20行)时,为什么这个简单的MPI发送和接收代码不在两个处理器上运行,而是在n上运行,我将不胜感激。死锁是正确的行为;代码中存在死锁 MPI规范允许一个简单的MPI程序,mpi,parallel-processing,sendmessage,Mpi,Parallel Processing,Sendmessage,如果有人告诉我,当n=40(第20行)时,为什么这个简单的MPI发送和接收代码不在两个处理器上运行,而是在n上运行,我将不胜感激。死锁是正确的行为;代码中存在死锁 MPI规范允许MPI\u Send表现为MPI\u Send——即阻塞。在某种意义上,阻塞通信原语在通信“完成”之前不会返回,这(在阻塞发送的情况下)可能意味着接收已经开始 您的代码如下所示: If Processor 0: Send to processor 1 If Processor 1: Send to proc
MPI\u Send
表现为MPI\u Send
——即阻塞。在某种意义上,阻塞通信原语在通信“完成”之前不会返回,这(在阻塞发送的情况下)可能意味着接收已经开始
您的代码如下所示:
If Processor 0:
Send to processor 1
If Processor 1:
Send to processor 0
Receive
也就是说,直到发送完成,接收才会开始。你在发送,但他们永远不会回来,因为没有人在接收!(这适用于小消息的事实是一个实现工件——大多数mpi实现使用所谓的“渴望协议”来处理“足够小”的消息;但这在一般情况下是不可靠的。)
请注意,这里还有其他逻辑错误——这个程序也会死锁超过2个处理器,因为秩>=2的处理器将等待一条永远不会出现的消息
您可以通过按等级交替发送和接收来修复程序:
if (processor_rank == 0) {
MPI_Send(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 1, 163, MPI_COMM_WORLD);
MPI_Recv(buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &status);
} else if (processor_rank == 1) {
MPI_Recv(buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &status);
MPI_Send(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 0, 163, MPI_COMM_WORLD);
}
或者使用MPI_Sendrecv(这是一种阻塞(发送+接收),而不是阻塞发送+阻塞接收):
或者通过使用非阻塞发送和接收:
MPI_Request reqs[2];
MPI_Status statuses[2];
if (processor_rank == 0) {
MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 1, 163, MPI_COMM_WORLD, &reqs[0]);
} else if (processor_rank == 1) {
MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 0, 163, MPI_COMM_WORLD, &reqs[0]);
}
if (processor_rank == 0 || processor_rank == 1)
MPI_Irecv(buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &reqs[1]);
MPI_Waitall(2, reqs, statuses);
谢谢乔纳森的帮助。在这里,我选择了第三种解决方案,并编写了与您类似的代码,只是添加了“for”循环以发送大量消息。这次它不会死锁;然而,处理器继续只接收最后一条消息。(由于消息很长,我只打印了最后的元素以检查一致性)
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int main(int argc,char*argv[])
{
整数处理器计数,处理器秩;
//初始化MPI
MPI_Init(&argc,&argv);
MPI通信大小(MPI通信世界和处理器计数);
MPI通信等级(MPI通信世界和处理器等级);
双**buff\u H,*buff\u send\u H;
int N_pa_prim1,l,N,N_p0,count,temp;
N_pa_prim1=5;l=7;N=50;N_p0=7;
MPI请求请求[N_pa_prim1];
MPI_状态状态[N_pa_prim1];
buff_H=new double*[N_pa_prim1];//接收缓冲区分配
对于(int i=0;iint sendto;
if (processor_rank == 0)
sendto = 1;
else if (processor_rank == 1)
sendto = 0;
if (processor_rank == 0 || processor_rank == 1) {
MPI_Sendrecv(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, sendto, 163,
buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163,
MPI_COMM_WORLD, &status);
}
MPI_Request reqs[2];
MPI_Status statuses[2];
if (processor_rank == 0) {
MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 1, 163, MPI_COMM_WORLD, &reqs[0]);
} else if (processor_rank == 1) {
MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 0, 163, MPI_COMM_WORLD, &reqs[0]);
}
if (processor_rank == 0 || processor_rank == 1)
MPI_Irecv(buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &reqs[1]);
MPI_Waitall(2, reqs, statuses);
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>
using namespace std;
int main(int argc, char *argv[])
{
int processor_count, processor_rank;
//Initialize MPI
MPI_Init (&argc, &argv);
MPI_Comm_size (MPI_COMM_WORLD, &processor_count);
MPI_Comm_rank (MPI_COMM_WORLD, &processor_rank);
double **buff_H, *buff_send_H;
int N_pa_prim1, l, n, N_p0, count, temp;
N_pa_prim1=5; l=7; n=50; N_p0=7;
MPI_Request reqs[N_pa_prim1];
MPI_Status statuses[N_pa_prim1];
buff_H = new double *[N_pa_prim1]; //Receive buffer allocation
for (int i = 0; i < N_pa_prim1; i++)
buff_H[i] = new double [n*n*N_p0+1];
buff_send_H = new double [n*n*N_p0+1]; //Send buffer allocation
if (processor_rank == 0) {
for (int i = 0; i < N_pa_prim1; i++){
for (int j = 0; j < n*n*N_p0+1; j++)
buff_send_H[j] = 2.0325e-8*rand();
cout << processor_rank << "\t" << buff_send_H[n*n*N_p0] << "\t" << "Send" << "\t" << endl;
MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 1, 163, MPI_COMM_WORLD, &reqs[i]);
}
}
else if (processor_rank == 1) {
for (int i = 0; i < N_pa_prim1; i++){
for (int j = 0; j < n*n*N_p0+1; j++)
buff_send_H[j] = 3.5871e-8*rand();
cout << processor_rank << "\t" << buff_send_H[n*n*N_p0] << "\t" << "Send" << "\t" << endl;
MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 0, 163, MPI_COMM_WORLD, &reqs[i]);
}
}
for (int i = 0; i < N_pa_prim1; i++)
MPI_Irecv(buff_H[i], n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &reqs[N_pa_prim1+i]);
MPI_Waitall(2*N_pa_prim1, reqs, statuses);
for (int i = 0; i < N_pa_prim1; i++)
cout << processor_rank << "\t" << buff_H[i][n*n*N_p0] << "\t" << "Receive" << endl;
MPI_Finalize();
return 0;