我的代码中有一个关于线性过程计算的阻塞

I have an interblockage in my code which is about linear process calculation

我们假设我们有一个 n 线性过程 P1...P2 ,每个过程都会与他的邻居(左和右)进行通信,并且我们有一个大小为 n 的向量 X ,& Xi= (X-1 + Xi + Xi+1 )/4 & 0< i < n-1 在这种情况下,每个进程 i 将数据 Xi 发送到他的邻居 Xi+1 & Xi-1 并从 i-1 & i+1 接收 Xi-1 & Xi+1 ,以计算 Xi

的新值

这就是我所做的,但我有一个中间阻塞,所以请帮助找出错误:

 #include<stdio.h>
#include<mpi.h>
#include <unistd.h>

int main(int argc, char *argv[]){

int world_rank;
int world_size; 
double rec=0,rec2=0;
int i,j;

MPI_Init (&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&world_rank);
MPI_Comm_size(MPI_COMM_WORLD,&world_size);
double x[world_size];

for(i=0;i<world_size;i++)x[i]=i;

for(i=0;i<world_size;i++){
    if(world_rank==i){
        if(world_rank==0){
            int a1=MPI_Send(&x[i],1,MPI_INT,i+1,0,MPI_COMM_WORLD);
            int a2=MPI_Recv(&rec,1,MPI_INT,i+1,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
            if((a1==MPI_SUCCESS)&&(a2==MPI_SUCCESS)){
                x[i]=(x[i]+rec)/4;  
                printf("x[%d]= %f\n",i,x[i]);
              }
            }else if(world_rank==world_size-1){
                            int a4=MPI_Send(&x[i],1,MPI_INT,i-1,0,MPI_COMM_WORLD);
                            int a3=MPI_Recv(&rec,1,MPI_INT,i-1,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);

                            if((a3==MPI_SUCCESS)&&(a4==MPI_SUCCESS)){
                                x[i]=(x[i]+rec)/4;  
                                printf("x[%d]= %f\n",i,x[i]);
                             }
                        }else{
                            int a7=MPI_Recv(&rec,1,MPI_INT,i+1,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE); 
                            int a8=MPI_Recv(&rec2,1,MPI_INT,i-1,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE); 
                            int a5=MPI_Send(&x[i],1,MPI_INT,i+1,0,MPI_COMM_WORLD);
                            int a6=MPI_Send(&x[i],1,MPI_INT,i-1,0,MPI_COMM_WORLD);

                            if((a5==MPI_SUCCESS)&&(a5==MPI_SUCCESS)&&(a5==MPI_SUCCESS)&&(a5==MPI_SUCCESS)){
                                x[i]=(x[i]+x[i+1]+x[i-1])/4;
                                    printf("x[%d]= %f\n",i,x[i]);
                            }
}                           
}
}

/*for(i=0;i<world_size;i++)
printf("x[%d]= %f\n",i,x[i]);*/

}

要理解死锁,想象一下如果使用两个进程会如何 运行:两个进程都会调用 MPI_Send(),其中 none 会收到消息,因为 MPI_Send() 正在阻塞。

因此,要克服这个问题,必须接收消息!有许多可用的解决方案:

  1. 根据 Hristo Iliev 的建议,您可以使用 MPI_Sendrecv()。实际上,OpenMPI cleary 的文档将您的情况称为 Sendrecv():
  2. 的典型用法

MPI_Sendrecv() combines in one call the sending of a message to one destination and the receiving of another message, from another process. A send-receive operation is useful for executing a shift operation across a chain of processes. If blocking sends and receives are used for such a shift, then one needs to order the sends and receives correctly (for example, even processes send, then receive; odd processes receive first, then send) in order to prevent cyclic dependencies that may lead to deadlock.

以下 example 说明了此选项。

  1. 可以通过函数MPI_Isend() and MPI_Irecv(). But there must be a call to a function like MPI_Waitall()使用非阻塞通信来保证所有的消息都真实的发送和接收。

    #include <mpi.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc,char *argv[])
    {
        int  world_size, world_rank;
        MPI_Init(&argc,&argv);
        MPI_Comm_size(MPI_COMM_WORLD,&world_size);
        MPI_Comm_rank(MPI_COMM_WORLD,&world_rank);
    
        int x[world_size];
    
        x[world_rank]=world_rank;
    
        int up=world_rank+1;
        int down=world_rank-1;
        if(up>=world_size){
            up=MPI_PROC_NULL;
        }
        if(down<0){
            down=MPI_PROC_NULL;
        }
        MPI_Request req[4];
        MPI_Isend(&x[world_rank], 1, MPI_INT, up, 0, MPI_COMM_WORLD, &req[0]); 
        MPI_Isend(&x[world_rank], 1, MPI_INT, down, 0, MPI_COMM_WORLD, &req[1]);
        MPI_Irecv(&x[(world_rank-1+world_size)%world_size], 1, MPI_INT, down, 0, MPI_COMM_WORLD, &req[2]);
        MPI_Irecv(&x[(world_rank+1+world_size)%world_size], 1, MPI_INT, up, 0, MPI_COMM_WORLD, &req[3]);
        MPI_Waitall(4, req, MPI_STATUSES_IGNORE);
    
        printf("rank %d has %d %d %d\n",world_rank,x[(world_rank-1+world_size)%world_size],x[world_rank],x[(world_rank+1+world_size)%world_size]); 
    
        MPI_Finalize();
        return 0;
    }
    

mpicc main.c -o main -Wall 编译,运行 由 mpirun -np 10 main 编译。