Bagaimana cara menghitung rasio persentase?
Saya baru mengenal mpi
dan saya mencoba menulis C
program mini yang menghitung rasio persentase angka yang dimasukkan pengguna.
Rasio persentase dihitung dengan ekspresi itu
`δi = ((xi – xmin ) / (xmax – xmin )) * 100`.
Angka-angka yang dimasukkan pengguna disimpan dalam array dengan ukuran tetap data[100]
dan tersebar ke semua proses (program ini seharusnya hanya bekerja dengan empat proses). Masalah yang saya hadapi adalah pembagian tidak berfungsi meskipun semua proses memiliki data. Misalnya jika pengguna memasukkan angka {1, 2, 3, 4}
, rasio persentase yang diharapkan sesuai dengan ekspresi matematika {0, 33.3, 66.6, 100}
tetapi sebaliknya saya dapatkan {0,0,100,100}
. Inilah yang saya miliki.
#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;
}
Jawaban
Ada beberapa masalah dengan kode Anda.
Pertama:
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);
sayangnya,
MPI tidak mendapatkan minimum semua elemen dalam array, Anda harus melakukannya secara manual. ( sumber )
Oleh karena itu, seseorang harus terlebih dahulu menghitung min
dan max
dalam setiap larik proses, dan kemudian seseorang dapat mengurangi itu min
dan max
hasilnya di antara proses lainnya. Karena, semua proses harus memiliki min
dan max
dari larik itu, alih-alih MPI_Reduce , Anda harus menggunakan MPI_Allreduce . Dan kode Anda akan terlihat seperti berikut:
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);
Kecuali Anda berasumsi bahwa loc_num=1
, yang seharusnya tidak Anda lakukan, kode ini
for(int j = 0; j< loc_num; j++){
x = loc_data[j] - global_min;
y = global_max - global_min;
}
mengesampingkan yang sama x
dan y
. Selain itu, Anda tidak boleh memanggil MPI_Bcast(&y, 1, MPI_INT, root, MPI_COMM_WORLD);
, Anda ingin semua proses menghitung secara paralel pekerjaan mereka terlebih dahulu berdasarkan rumus:
δi = ((xi – xmin ) / (xmax – xmin )) * 100.
dan baru kemudian mengirimkan pekerjaan mereka kembali ke proses master . Jadi setiap proses harus menerapkan rumus itu ke indeks masukan mereka, menyimpan hasilnya dalam larik dan mengirimkannya kembali ke proses utama . Seperti ini:
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);
Perhatikan bahwa saya melakukan casting (((float) (loc_data[j] - global_min) / y) * 100.0);
untuk mengapung . Jika tidak, C
akan mengembalikan int
representasi dari hasil.