Wie berechnet man das prozentuale Verhältnis?
Ich bin neu in mpi
und versuche, ein Miniprogramm zu schreiben C
, das das prozentuale Verhältnis der vom Benutzer eingegebenen Zahlen berechnet .
Das prozentuale Verhältnis wird durch diesen Ausdruck berechnet
`δi = ((xi – xmin ) / (xmax – xmin )) * 100`.
Die vom Benutzer eingegebenen Zahlen werden in einem Array fester Größe gespeichert data[100]
und auf alle Prozesse verteilt (dieses Programm soll nur mit vier Prozessen arbeiten). Das Problem, mit dem ich konfrontiert bin, ist, dass die Aufteilung nicht funktioniert, obwohl alle Prozesse die Daten haben. Wenn der Benutzer zum Beispiel die Zahlen eingibt, ist {1, 2, 3, 4}
das erwartete prozentuale Verhältnis gemäß dem mathematischen Ausdruck, {0, 33.3, 66.6, 100}
aber stattdessen erhalte ich {0,0,100,100}
. Das habe ich.
#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;
}
Antworten
Es gibt verschiedene Probleme mit Ihrem Code.
Zuerst:
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);
Unglücklicherweise,
MPI erhält nicht das Minimum aller Elemente im Array, Sie müssen dies manuell tun. ( Quelle )
Daher muss man zuerst das min
und das max
Array jedes Prozesses berechnen , und dann kann man diese min
und die max
Ergebnisse unter den anderen Prozessen reduzieren . Da alle Prozesse das min
und max
dieses Arrays anstelle von MPI_Reduce haben sollten, sollten Sie MPI_Allreduce verwenden . Und Ihr Code würde wie folgt aussehen:
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);
Es sei denn, Sie gehen davon aus, dass loc_num=1
Sie diesen Code nicht sollten
for(int j = 0; j< loc_num; j++){
x = loc_data[j] - global_min;
y = global_max - global_min;
}
überschreibt das gleiche x
und y
. Darüber hinaus sollten Sie nicht aufrufen MPI_Bcast(&y, 1, MPI_INT, root, MPI_COMM_WORLD);
, Sie möchten, dass alle Prozesse zuerst parallel ihre Arbeit basierend auf der Formel berechnen:
δi = ((xi – xmin ) / (xmax – xmin )) * 100.
und erst dann senden Sie ihre Arbeit an den Master- Prozess zurück. Daher sollte jeder Prozess diese Formel auf seine Eingabeindizes anwenden, die Ergebnisse in einem Array speichern und an den Masterprozess zurücksenden. Wie so:
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);
Beachten Sie, dass ich (((float) (loc_data[j] - global_min) / y) * 100.0);
zum Schweben gieße . Andernfalls C
würde eine int
Darstellung des Ergebnisses zurückgegeben.