首页 > 解决方案 > mpi程序出现不可预知的错误——主进程运行两次

问题描述

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

int main(int argc, char *argv[])
{
    int rank, value, size,count;
    MPI_Status status;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    count=2*size-1;
    while(count>0){
        if (rank==0) {
            // fprintf(stderr, "\nPlease give new value=");
            printf("please input value= ");
            scanf("%d",&value);
            // fprintf(stderr, "%d read <-<- (%d)\n",rank,value);
            printf("%d read <-<- (%d)\n",rank,value);
            count-=1;
    
            if (size>1) {
                MPI_Send(&value, 1, MPI_INT, rank+1, 0, MPI_COMM_WORLD);
                // fprintf(stderr, "%d send (%d)->-> %d\n", rank,value,rank+1);
                printf("%d send (%d)->-> %d\n",rank,value,rank+1);
                count-=1;
            }
        }
        else {
            MPI_Recv(&value, 1, MPI_INT, rank-1, 0, MPI_COMM_WORLD, &status);
            // fprintf(stderr, "%d receive(%d)<-<- %d\n",rank, value, rank-1);
            printf("%d receive(%d)<-<- %d\n",rank, value, rank-1);
            count-=1;
            if (rank<size-1) {
                MPI_Send(&value, 1, MPI_INT, rank+1, 0, MPI_COMM_WORLD);
                fprintf(stderr, "%d send (%d)->-> %d\n", rank, value, rank+1);
            count-=1;
            }
        }
        MPI_Barrier(MPI_COMM_WORLD);
    }
    MPI_Finalize();
}

该程序的功能是在进程之间传递数字。现在我打开两个传递数字 4 的进程

在此处输入图像描述

但是 0 进程运行了两次,并没有达到预期的效果。

然后我用gdb调试

在此处输入图像描述

这一直困扰着我很长时间,我不太擅长从命令行看变量。请帮我。

标签: clinuxparallel-processinggdbmpi

解决方案


TL;DR:它运行两次,因为while循环执行了两次。

但是 0 进程运行了两次,并没有达到预期的效果。

您的印象是进程0运行了两次,因为count在进入while循环之前的变量的值是3from count=2*size-1;size是 2,因为您正在运行 2 个进程)。

在你的循环中:

while(count>0){
        if (rank==0) {
            ...
            count-=1;
    
            if (size>1) {
                ...
                count-=1;
            }
        }
        else {
            ...
            count-=1;
            if (rank<size-1) {
               ...
            count-=1;
            }
        }
        MPI_Barrier(MPI_COMM_WORLD);
    }

对于(进程0),该count变量减少了两次,因此count为1,并且由于while循环条件是count>0,它在退出之前再次执行。因此,进程0“再次运行”。

该过程将变量0递减两次,而该过程仅减少一次,因此很可能是一个错误。您可能会遇到进程阻塞等待从进程接收消息但进程已经在循环之外的情况。count1100

要测试进程中消息的发送和接收,请0尝试以下操作:

int main(int argc, char *argv[])
{
    int rank, value, size,count;
    MPI_Status status;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    if (rank==0) 
    {
       printf("please input value= ");
       scanf("%d",&value);
       for(int i = 1; i < size; i++){
           MPI_Send(&value, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
           printf("%d send (%d)->-> %d\n",rank, value, i);
      }
    }
    else 
    {
       MPI_Recv(&value, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
       printf("%d receive(%d)<-<- %d\n",rank, value, rank-1);
    }
    MPI_Finalize();
}

进程0向所有剩余进程发送一个值:

   for(int i = 1; i < size; i++){
       MPI_Send(&value, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
       printf("%d send (%d)->-> %d\n",rank, value, i);
  }

并且所有剩余的进程都会收到来自进程的消息0

MPI_Recv(&value, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);

推荐阅读