วิธีคำนวณอัตราส่วนร้อยละ
ฉันเพิ่งใหม่mpi
และฉันกำลังพยายามเขียนC
โปรแกรมขนาดเล็กที่คำนวณอัตราส่วนเปอร์เซ็นต์ของตัวเลขที่ผู้ใช้ป้อน
อัตราส่วนเปอร์เซ็นต์คำนวณโดยนิพจน์นั้น
`δi = ((xi – xmin ) / (xmax – xmin )) * 100`.
ตัวเลขที่อินพุตของผู้ใช้จะถูกเก็บไว้ในอาร์เรย์ที่มีขนาดคงที่data[100]
และกระจัดกระจายไปยังกระบวนการทั้งหมด (โปรแกรมนี้ควรจะทำงานกับสี่กระบวนการเท่านั้น) ปัญหาที่ฉันพบคือการแบ่งไม่ทำงานแม้ว่ากระบวนการทั้งหมดจะมีข้อมูล ตัวอย่างเช่นหากผู้ใช้ป้อนตัวเลข{1, 2, 3, 4}
ที่อัตราส่วนเปอร์เซ็นต์ที่คาดไว้ตามนิพจน์ทางคณิตศาสตร์{0, 33.3, 66.6, 100}
แต่ฉันได้รับ{0,0,100,100}
แทน นี่คือสิ่งที่ฉันมี
#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;
}
คำตอบ
มีปัญหาหลายประการเกี่ยวกับรหัสของคุณ
อันดับแรก:
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);
น่าเสียดาย,
MPI ไม่ได้รับองค์ประกอบขั้นต่ำทั้งหมดในอาร์เรย์คุณต้องดำเนินการด้วยตนเอง (ที่มา )
ดังนั้นหนึ่งความต้องการในการคำนวณครั้งแรกmin
และmax
ภายในอาร์เรย์แต่ละขั้นตอนและจากนั้นหนึ่งสามารถลดเหล่านั้นmin
และmax
ผลในหมู่กระบวนการอื่น ๆ ตั้งแต่กระบวนการทั้งหมดควรจะมีmin
และmax
ของอาร์เรย์ที่แทนของMPI_Reduceคุณควรใช้MPI_Allreduce และรหัสของคุณจะมีลักษณะดังต่อไปนี้:
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);
เว้นแต่คุณจะสมมติว่าloc_num=1
คุณไม่ควรใช้รหัสนี้
for(int j = 0; j< loc_num; j++){
x = loc_data[j] - global_min;
y = global_max - global_min;
}
แทนที่สิ่งเดียวกันx
และy
. ยิ่งไปกว่านั้นคุณไม่ควรโทรหาMPI_Bcast(&y, 1, MPI_INT, root, MPI_COMM_WORLD);
คุณต้องการให้กระบวนการทั้งหมดคำนวณแบบขนานงานของพวกเขาก่อนตามสูตร:
δi = ((xi – xmin ) / (xmax – xmin )) * 100.
จากนั้นจึงส่งงานของพวกเขากลับไปที่กระบวนการหลักเท่านั้น ดังนั้นแต่ละกระบวนการควรใช้สูตรนั้นกับดัชนีอินพุตเก็บผลลัพธ์ไว้ในอาร์เรย์และส่งกลับไปยังกระบวนการหลัก ชอบมาก:
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);
แจ้งให้ทราบว่าผมหล่อ(((float) (loc_data[j] - global_min) / y) * 100.0);
จะลอย มิฉะนั้นC
จะส่งกลับการเป็นint
ตัวแทนของผลลัพธ์