一个简单的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

如果有人告诉我,当n=40(第20行)时,为什么这个简单的MPI发送和接收代码不在两个处理器上运行,而是在n上运行,我将不胜感激。死锁是正确的行为;代码中存在死锁

MPI规范允许
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;