并行数组元素的总和?

Sum of the element of an array in parallel?

我正在尝试编写一个 MPI 程序来计算整数数组的总和。

为此,我使用 MPI_Scatter 将数组块发送到其他进程,然后 MPI_Gather 由根进程(进程 0)获取每个块的总和。

问题是其中一个进程接收两个元素,而另一个进程接收随机数。我 运行 我的代码有 3 个进程。

这是我的资料:

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

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

    MPI_Init(NULL,NULL); // Initialize the MPI environment

    int world_rank; 
    int world_size;

    MPI_Comm_rank(MPI_COMM_WORLD,&world_rank);
    MPI_Comm_size(MPI_COMM_WORLD,&world_size);

    int number1[2]; //buffer for processes
    int sub_sum = 0; 
    int sub_sums[2]; 
    int sum;

    int number[4];

    if(world_rank == 0){
       number[0]=1;
       number[1]=3;
       number[2]=5;
       number[3]=9;
    }
    //All processes
    MPI_Scatter(number, 2, MPI_INT, &number1, 2, MPI_INT, 0, MPI_COMM_WORLD);

    if(world_rank!=0){
       printf("I'm process %d , I received the array : ",world_rank);
       for(int i=0 ; i<2 ; i++){
           printf("%d ",number1[i]);
           sub_sum = sub_sum + number1[i];
       }
       printf("\n");
   }

   MPI_Gather(&sub_sum, 1, MPI_INT, &sub_sums, 1, MPI_INT, 0,MPI_COMM_WORLD);

   if(world_rank == 0){
      sum=0;
      for(int i=0; i<2;i++){
          sum+= sub_sums[i];
        }
        printf("\nthe sum of array is: %d\n",sum);
  }

   MPI_Finalize();
   return 0;
}

结果:

I'm process 1 , I received the array : 5 9 
I'm process 2 , I received the array : 1494772352 32767 

the sum of array is: 14

看来您误解了 MPI 的工作原理;您的代码被硬编码为仅在两个进程中(正确地)工作。但是,您正在尝试 运行 具有 3 个进程的代码,错误的假设是在 MPI_Scatter 调用期间根级别只会将数据发送到其他进程。如果您看下图(摘自 source):

您注意到根等级(等级= 0)也接收了部分数据。

The problem is one of the processes receives two elements but the other one receives random numbers.

MPI_Scatter(number, 2, MPI_INT, &number1, 2, MPI_INT, 0, MPI_COMM_WORLD);

因此您已将输入硬编码如下 number{1,3,5,9}(只有 4 个元素);在 MPI_Scatter 调用期间发生的是 process 0 将从数组 number 中获取第一个和第二个元素( {1, 3}),而 process 1 得到另外两个元素( {5, 9}),而 process 2 将得到一些随机值,因此:

I'm process 2 , I received the array : 1494772352 32767

你得到

数组之和为:14

因为数组 sub_sums 将由 process 0process 1 执行总和,因为你排除了它,它是零,而 process 1 是 3 + 9。因此,0 + 14 = 14.

要解决此问题,您需要从以下位置删除 if(world_rank!=0)

  if(world_rank!=0){
    printf("I'm process %d , I received the array : ",world_rank);
    for(int i=0 ; i<2 ; i++){
        printf("%d ",number1[i]);
        sub_sum = sub_sum + number1[i];
    }
     printf("\n");
 }

和运行您的代码只有 2 个进程。

对于最后一步而不是 MPI_Gather,您可以使用 MPI_Reduce 并行执行求和并直接在根等级上收集值。因此,您不需要在根等级上手动执行求和。

一个运行宁例子:

int main(int argc,char *argv[]){
    MPI_Init(NULL,NULL); // Initialize the MPI environment
    int world_rank; 
    int world_size;
    MPI_Comm_rank(MPI_COMM_WORLD,&world_rank);
    MPI_Comm_size(MPI_COMM_WORLD,&world_size);
    
    int number1[2];           
    int number[4];
    if(world_rank == 0){
      number[0]=1;
      number[1]=3;
      number[2]=5;
      number[3]=9;               
    }

    //All processes
    MPI_Scatter(number, 2, MPI_INT, &number1, 2, MPI_INT, 0, MPI_COMM_WORLD);
    printf("I'm process %d , I received the array : ",world_rank);
       
    int sub_sum = 0;
    for(int i=0 ; i<2 ; i++){
        printf("%d ",number1[i]);
        sub_sum = sub_sum + number1[i];
    }
    printf("\n");        
    int sum = 0;
    MPI_Reduce(&sub_sum, &sum, 1, MPI_INT, MPI_SUM,0,MPI_COMM_WORLD);            
    if(world_rank == 0)
      printf("\nthe sum of array is: %d\n",sum);
            

    MPI_Finalize();
    return 0;
 }

输入 : {1,3,5,9} 运行 2 个进程

输出

I'm process 0 , I received the array : 1 3 
I'm process 1 , I received the array : 5 9 

the sum of array is: 18

如果您真的只想让进程 1 和 2 接收数据并执行求和,我建议查看例程 MPI_Send and MPI_Recv