微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

并行数组元素的总和?

如何解决并行数组元素的总和?

我正在尝试编写一个 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,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,&sub_sums,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):

enter image description here

您注意到根排名( rank = 0)也接收部分数据。

问题是其中一个进程接收了两个元素,但是 另一个接收随机数。

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

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

我正在处理 2 ,我收到了数组:1494772352 32767

你得到

数组的总和为:14

因为数组 sub_sums 将具有由 process 0 执行的总和,因为您排除了它为零,而 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,MPI_COMM_WORLD);
    printf("I'm process %d,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_SUM,MPI_COMM_WORLD);            
    if(world_rank == 0)
      printf("\nthe sum of array is: %d\n",sum);
            

    MPI_Finalize();
    return 0;
 }

输入:{1,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_SendMPI_Recv

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。