प्रतिशत अनुपात की गणना कैसे करें?

Jan 06 2021

मैं नया 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;
}

जवाब

2 dreamcrash Jan 06 2021 at 22:23

आपके कोड के साथ कई समस्याएं हैं।

प्रथम:

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परिणामों को कम कर सकता है। चूंकि, सभी प्रक्रियाओं में MPI_Reduce के बजाय उस सरणी का minऔर होना चाहिए, आपको MPI_Allreduce का उपयोग करना चाहिए । और आपका कोड निम्नलिखित की तरह दिखेगा:max

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); लिए कास्टिंग कर रहा हूं । अन्यथा, परिणाम का एक प्रतिनिधित्व लौटाएगा ।Cint