我的代码中有一个interblockage,它涉及线性过程计算

时间:2016-10-26 21:02:24

标签: c linux process mpi linear

我们假设我们有一个n线性过程P1 ... P2,&每个过程都会与他的邻居(左右)和&我们有一个大小为n的向量X,& Xi =(X-1 + Xi + Xi + 1)/ 4& 0℃;我< n-1个 在这种情况下,每个进程都将数据Xi发送给他的邻居Xi + 1& Xi-1和Xi-1&来自i-1&的Xi + 1 i + 1,用于计算Xi的新值

这就是我所做的,但我有一个interblockage,所以请帮助找到错误:

 #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]);*/

}

2 个答案:

答案 0 :(得分:0)

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

因此,要克服这个问题,必须收到消息!有许多解决方案可供选择:

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

    MPI_Sendrecv()在一次调用中将消息发送到一个目的地并从另一个进程接收另一个消息。发送 - 接收操作对于在一系列进程中执行移位操作很有用。如果阻塞发送和接收用于这种移位,则需要正确地命令发送和接收(例如,甚至进程发送,然后接收;奇数进程首先接收,然后发送)以防止可能导致的循环依赖性陷入僵局。

    以下example说明了此选项。

    1. 可以通过函数MPI_Isend()MPI_Irecv()使用非阻止通信。但是必须调用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;
      }
      
    2. mpicc main.c -o main -Wall编译并由mpirun -np 10 main运行。

答案 1 :(得分:0)

试试这个代码,我没有得到发送的价值!为什么? @francis

#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);

    double x[world_size];
        double rec=0,rec2=0;
    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(&rec2, 1, MPI_INT, up, 0, MPI_COMM_WORLD, &req[3]);
    MPI_Irecv(&rec, 1, MPI_INT, down, 0, MPI_COMM_WORLD, &req[2]);
    MPI_Waitall(4, req, MPI_STATUSES_IGNORE);
        printf("im process %d rec= %f & rec2=%f \n",world_rank,rec,rec2);
        x[world_rank]=(rec+x[world_rank]+rec2)/4;
        printf("x[%d]= %f\n",world_rank,x[world_rank]);
    MPI_Finalize();
    return 0;
}