¿Cómo calcular la relación porcentual?
Soy nuevo mpi
y estoy tratando de escribir un mini C
programa que calcule la proporción porcentual de números que ingresa el usuario.
La relación porcentual se calcula mediante esa expresión
`δi = ((xi – xmin ) / (xmax – xmin )) * 100`.
Los números que ingresa el usuario se almacenan en una matriz de tamaño fijo data[100]
y están dispersos en todos los procesos (se supone que este programa solo funciona con cuatro procesos). El problema al que me enfrento es que la división no funciona aunque todos los procesos tienen los datos. Por ejemplo, si el usuario ingresa los números, {1, 2, 3, 4}
la proporción porcentual esperada de acuerdo con la expresión matemática es, {0, 33.3, 66.6, 100}
pero en cambio estoy obteniendo {0,0,100,100}
. Esto es lo que tengo.
#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;
}
Respuestas
Hay varios problemas con su código.
Primero:
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);
Desafortunadamente,
MPI no obtiene el mínimo de todos los elementos de la matriz, debe hacerlo manualmente. ( fuente )
Por lo tanto, primero se necesita calcular el min
y max
dentro de la matriz de cada proceso, y luego se pueden reducir esos min
y los max
resultados entre los otros procesos. Dado que, todos los procesos deben tener el min
y max
de esa matriz, en lugar de MPI_Reduce , debe usar MPI_Allreduce . Y su código se vería así:
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 menos que esté asumiendo que loc_num=1
, lo cual no debería, este código
for(int j = 0; j< loc_num; j++){
x = loc_data[j] - global_min;
y = global_max - global_min;
}
anula lo mismo x
y y
. Además, no debe llamar MPI_Bcast(&y, 1, MPI_INT, root, MPI_COMM_WORLD);
, desea que todos los procesos calculen primero en paralelo su trabajo en función de la fórmula:
δi = ((xi – xmin ) / (xmax – xmin )) * 100.
y solo entonces enviar su trabajo de vuelta al proceso maestro . Entonces, cada proceso debe aplicar esa fórmula a sus índices de entrada, almacenar los resultados en una matriz y enviarlos de vuelta al proceso maestro . Al igual que:
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);
Observe que estoy lanzando (((float) (loc_data[j] - global_min) / y) * 100.0);
para flotar . De C
lo contrario, devolvería una int
representación del resultado.