Cách tính tỉ số phần trăm?

Jan 06 2021

Tôi mới đến mpivà tôi đang cố gắng để viết một mini Cchươ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

2 dreamcrash Jan 06 2021 at 22:23

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 minmaxbên trong mỗi quá trình, sau đó người ta có thể giảm những cái đó minmaxkết quả giữa các quá trình khác. Vì tất cả các quy trình phải có minmaxcủ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 xy. 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, Csẽ trả về một intđại diện của kết quả.