2 votes

Somme des éléments d'un tableau en parallèle ?

J'essaie d'écrire un programme MPI qui calcule la somme d'un tableau d'entiers.

À cette fin, j'ai utilisé MPI_Scatter pour envoyer des morceaux du tableau aux autres processus, puis MPI_Gather pour obtenir la somme de chaque morceau par le processus racine (processus 0).

Le problème est que l'un des processus reçoit deux éléments mais que l'autre reçoit des nombres aléatoires. J'exécute mon code avec 3 processus.

Voici ce que j'ai :

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

Le résultat :

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

3voto

dreamcrash Points 8227

Il semble que vous ayez mal compris le fonctionnement de MPI. Votre code est codé en dur pour fonctionner (correctement) avec seulement deux processus. Cependant, vous essayez d'exécuter le code avec 3 processus, avec l'hypothèse erronée que pendant la phase d'exécution de la fonction MPI_Scatter appeler le rang racine n'enverra les données qu'aux autres processus. Si vous regardez l'image suivante (tirée de source ):

enter image description here

vous remarquez que le rang racine ( c'est-à-dire, rang = 0) reçoit également une partie des données.

Le problème est que l'un des processus reçoit deux éléments, mais que l'autre n'en reçoit pas. l'autre reçoit des nombres aléatoires.

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

Vous avez donc codé en dur une entrée comme suit number{1,3,5,9} (avec seulement 4 éléments) ; et ce qui se passe lors de la MPI_Scatter est que process 0 récupère les premier et deuxième éléments du tableau number ( c'est-à-dire, {1, 3} ), tandis que les process 1 obtient les deux autres éléments ( c'est-à-dire, {5, 9} ), et le process 2 obtiendra donc des valeurs aléatoires :

Je suis le processus 2, j'ai reçu le tableau : 1494772352 32767

Vous obtenez

la somme du tableau est : 14

car le tableau sub_sums fera effectuer les sommes par process 0 qui est nul puisque vous avez exclu, et process 1 qui est égal à 3 + 9. D'où, 0 + 14 = 14 .

Pour remédier à ce problème, vous devez supprimer if(world_rank!=0) de :

  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");
 }

et d'exécuter votre code avec seulement 2 processus.

Pour la dernière étape, au lieu du MPI_Gather vous pouvez utiliser MPI_Reduce d'effectuer la somme en parallèle et de collecter la valeur directement sur le rang racine. Par conséquent, il n'est pas nécessaire d'effectuer la somme manuellement sur le rang racine.

Un exemple concret :

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;
 }

Entrée : {1,3,5,9} fonctionnant avec 2 processus

Sortie

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

Si vous vraiment Si vous souhaitez que seuls les processus 1 et 2 reçoivent les données et effectuent la somme, je vous suggère de vous pencher sur les routines MPI_Send y MPI_Recv .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X