2 votes

Comment calculer le ratio en pourcentage ?

Je suis nouveau dans mpi et j'essaie d'écrire un mini C un programme qui calcule le pourcentage rapport de chiffres que l'utilisateur saisit.

Le rapport en pourcentage est calculé par cette expression

`i = ((xi – xmin ) / (xmax – xmin )) * 100`. 

Les nombres que l'utilisateur saisit sont stockés dans un tableau de taille fixe. data[100] et sont dispersés dans tous les processus (ce programme est censé fonctionner uniquement avec quatre processus). Le problème auquel je suis confronté est que la division ne fonctionne pas bien que tous les processus aient les données. Par exemple, si l'utilisateur saisit les chiffres {1, 2, 3, 4} le rapport en pourcentage attendu, selon l'expression mathématique, est le suivant {0, 33.3, 66.6, 100} mais au lieu de cela, j'obtiens {0,0,100,100} . Voici ce que j'ai.

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

int main(int argc, char** argv){
    int my_rank;
    int total_processes;
    int root = 0;
    int data[100];
    int loc_data[100];

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &total_processes);

    int input_size = 0;
    if (my_rank == 0){
        printf("Input how many numbers: ");
        scanf("%d", &input_size);

        printf("Input the elements of the array: ");
        for(int i=0; i<input_size; i++){
            scanf("%d", &data[i]);
        }
    }

    MPI_Bcast(&input_size, 1, MPI_INT, root, MPI_COMM_WORLD);

    int loc_num = input_size/total_processes;

    MPI_Scatter(&data, loc_num, MPI_INT, loc_data, loc_num, MPI_INT, root, MPI_COMM_WORLD);

    int global_max = 0;
    int global_min = 0;
    MPI_Reduce(&loc_data, &global_max, 1, MPI_INT, MPI_MAX, root, MPI_COMM_WORLD);
    MPI_Reduce(&loc_data, &global_min, 1, MPI_INT, MPI_MIN, root, MPI_COMM_WORLD);

    float loc_delta[100];
    int x = 0;
    int y = 0;
    float p = 0;

     for(int j = 0; j< loc_num; j++){
        x = loc_data[j] - global_min;
        y = global_max - global_min;
    }

    MPI_Bcast(&y, 1, MPI_INT, root, MPI_COMM_WORLD); 

    for(int j = 0; j< loc_num ; j++){
        p = (x / y) * 100;
        printf("p= %f \n", p);
        loc_delta[j] = p; 
    }

    float final_delta[100];
    MPI_Gather(&loc_delta, 1, MPI_FLOAT, final_delta, 1, MPI_FLOAT, root, MPI_COMM_WORLD);

    if(my_rank == 0){
        printf("max number: %d\n", global_max);
        printf("min number: %d\n", global_min);

        for(int i = 0; i<input_size; i++)
            printf("delta[%d]: %.2f | ", i+1, final_delta[i]);
    }

    printf("\n");

        MPI_Finalize();

    return 0;
}

2voto

dreamcrash Points 8227

Il y a plusieurs problèmes avec votre code.

D'abord :

int global_max = 0;
int global_min = 0;
MPI_Reduce(&loc_data, &global_max, 1, MPI_INT, MPI_MAX, root, MPI_COMM_WORLD);
MPI_Reduce(&loc_data, &global_min, 1, MPI_INT, MPI_MIN, root, MPI_COMM_WORLD);

malheureusement,

MPI n'obtient pas le minimum de tous les éléments du tableau, vous devez donc le faire manuellement. ( source )

Par conséquent, il faut d'abord calculer le min et le max à l'intérieur du tableau de chaque processus, et ensuite on peut réduire ces min y max les résultats parmi les autres processus. Puisque, tous les processus doivent avoir le min y max de ce tableau, au lieu de MPI_Reduce vous devez utiliser MPI_Allreduce . Et votre code ressemblerait à ce qui suit :

int local_max = loc_data[0];
int local_min = loc_data[0];
for(int i = 1; i < loc_num; i++){
   local_max = (local_max > loc_data[i]) ?  local_max : loc_data[i];
   local_min = (local_min < loc_data[i]) ?  local_min : loc_data[i];  
}

int global_max = local_max;
int global_min = local_min;

MPI_Allreduce(&local_max, &global_max, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
MPI_Allreduce(&local_min, &global_min, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);

A moins que vous ne supposiez que loc_num=1 ce que vous ne devriez pas faire, ce code

  for(int j = 0; j< loc_num; j++){
        x = loc_data[j] - global_min;
        y = global_max - global_min;
    }

remplace le même x y y . De plus, vous ne devez pas appeler MPI_Bcast(&y, 1, MPI_INT, root, MPI_COMM_WORLD); vous voulez que tous les processus calculent d'abord en parallèle leur travail sur la base de la formule :

i = ((xi – xmin ) / (xmax – xmin )) * 100.

et ne renvoient qu'ensuite leur travail à la maître processus. Ainsi, chaque processus doit appliquer cette formule à ses indices d'entrée, stocker les résultats dans un tableau et les renvoyer à l'unité de gestion de l'information. maître processus. Comme ça :

float loc_delta[100];
float y = global_max - global_min;
for(int j = 0; j< loc_num; j++){
    loc_delta[j] = (((float) (loc_data[j] - global_min) / y) * 100.0); 
}

float final_delta[100];
MPI_Gather(&loc_delta, loc_num, MPI_FLOAT, final_delta, loc_num, MPI_FLOAT, root, MPI_COMM_WORLD);

Remarquez que je lance (((float) (loc_data[j] - global_min) / y) * 100.0); à float . Autrement, C retournerait un int représentation du résultat.

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