Cách tính tỉ số phần trăm?
Tôi mới đến mpi
và tôi đang cố gắng để viết một mini C
chương trình cho phép tính tỷ lệ phần trăm tỷ lệ của số mà đầu vào người dùng.
Tỷ lệ phần trăm được tính bằng biểu thức đó
`δi = ((xi – xmin ) / (xmax – xmin )) * 100`.
Các số mà người dùng đầu vào được lưu trữ trong một mảng có kích thước cố định data[100]
và được phân tán cho tất cả các quy trình (chương trình này được cho là chỉ hoạt động với bốn quy trình). Vấn đề tôi đang gặp phải là sự phân chia không hoạt động mặc dù tất cả các quy trình đều có dữ liệu. Ví dụ: nếu người dùng nhập các số {1, 2, 3, 4}
, tỷ lệ phần trăm dự kiến theo biểu thức toán học là {0, 33.3, 66.6, 100}
nhưng thay vào đó tôi nhận được {0,0,100,100}
. Đây là những gì tôi có.
#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;
}
Trả lời
Có một số vấn đề với mã của bạn.
Đầu tiên:
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);
không may,
MPI không nhận được tối thiểu tất cả các phần tử trong mảng, bạn phải làm điều đó theo cách thủ công. ( nguồn )
Do đó, trước tiên người ta cần phải tính toán mảng min
và max
bên trong mỗi quá trình, sau đó người ta có thể giảm những cái đó min
và max
kết quả giữa các quá trình khác. Vì tất cả các quy trình phải có min
và max
của mảng đó, thay vì MPI_Reduce , bạn nên sử dụng MPI_Allreduce . Và mã của bạn sẽ giống như sau:
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);
Trừ khi bạn đang giả định điều đó loc_num=1
, điều mà bạn không nên, mã này
for(int j = 0; j< loc_num; j++){
x = loc_data[j] - global_min;
y = global_max - global_min;
}
ghi đè giống nhau x
và y
. Hơn nữa, bạn không nên gọi MPI_Bcast(&y, 1, MPI_INT, root, MPI_COMM_WORLD);
, bạn muốn tất cả các quy trình trước tiên phải tính toán song song công việc của chúng dựa trên công thức:
δi = ((xi – xmin ) / (xmax – xmin )) * 100.
và chỉ sau đó gửi trở lại công việc của mình với thầy quá trình. Vì vậy, mỗi quá trình nên áp dụng công thức đó để chỉ số đầu vào của họ, lưu trữ các kết quả trong một mảng và gửi nó trở lại tổng thể quá trình. Như vậy:
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);
Lưu ý rằng tôi đang đúc (((float) (loc_data[j] - global_min) / y) * 100.0);
để nổi . Nếu không, C
sẽ trả về một int
đại diện của kết quả.