2015-11-02 4 views
1

Я пытаюсь изучить MPI, написав программу для вычисления коэффициента. Однако моя программа фактически замедляется после внедрения MPI. Вот мой код:Замедление после реализации MPI

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#include <time.h> 
#include <mpi.h> 

#define aSize 2000000 

double stan_dev_mpi(double stan_array[], double stan_mean){ 

    double a = 0; 
    double atemp = 0; 

    for (int i=0; i<aSize; i++){ 
     a = a + pow((stan_array[i]-stan_mean), 2); 
    } 

    MPI_Allreduce(&a, &atemp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); 

    a = a/aSize; 

    a = sqrt(a); 

    return a; 
} 

double mean(double* mean_array){ 
    double mean = 0; 

    for (int i=0; i<aSize; i++){ 
     mean = mean + mean_array[i]; 
    } 


    mean = mean/aSize; 

    return mean; 

} 

int pearson_par(void){ 

    int comm_sz; 
    int my_rank; 

    double mean_a; 
    double mean_b; 

    MPI_Init(NULL, NULL); 
    MPI_Comm_size(MPI_COMM_WORLD, &comm_sz); 
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); 



    double *a; 
    a = malloc(sizeof(double)*aSize); 


    double *b; 
    b = malloc(sizeof(double)*aSize); 

    for (int i=0; i<aSize; i++){ 
     a[i] = sin(i); 
     b[i] = sin(i+2);  

    } 

    clock_t begin, end; 
    double time_spent; 

    begin = clock(); 





    double *buffera = (double *)malloc(sizeof(double) * (aSize/comm_sz)); 
    double *bufferb = (double *)malloc(sizeof(double) * (aSize/comm_sz)); 

    MPI_Scatter(a, aSize/comm_sz, MPI_DOUBLE, buffera, aSize/comm_sz, MPI_DOUBLE, 0, MPI_COMM_WORLD); 
    MPI_Scatter(b, aSize/comm_sz, MPI_DOUBLE, bufferb, aSize/comm_sz, MPI_DOUBLE, 0, MPI_COMM_WORLD); 



    mean_a = mean(a); 
    mean_b = mean(a); 

    double stan_dev_a = stan_dev_mpi(a, mean_a); 
    double stan_dev_b = stan_dev_mpi(b, mean_b); 
    double pearson_numer; 
    double pearson_numer_temp; 

    for(int i=0; i<aSize; i++){ 
     pearson_numer = pearson_numer + ((a[i]-mean_a)*(b[i]-mean_b)); 
    } 

    MPI_Allreduce(&pearson_numer, &pearson_numer_temp, 1, MPI_DOUBLE, MPI_SUM, 
       MPI_COMM_WORLD); 

    pearson_numer = pearson_numer/aSize; 

    double pearson_coef = pearson_numer/(stan_dev_a*stan_dev_b); 

    if(my_rank == 0){ 

    printf("%s %G\n", "The Pearson Coefficient is: ", pearson_coef); 

    } 


    end = clock(); 

    time_spent = (double)(end - begin)/CLOCKS_PER_SEC; 


    if(my_rank == 0){ 

    printf("%lf %s\n", time_spent, "sec"); 

    } 



    MPI_Finalize(); 


    free(a); 
    free(b); 

    return 0; 
} 

int main(void) { 

    pearson_par(); 

return 0; 
} 

И если я запускаю его с 4-мя процессами я получаю время работы 0,06 по сравнению с 0,03, когда бежал с последовательной версией. Я новичок в MPI, поэтому не уверен, что вызывает проблему. Любая помощь будет оценена по достоинству.

+0

Сохраняется ли уменьшение скорости, даже если вы увеличиваете счет? Может быть много накладных расходов относительно рабочей нагрузки. –

+0

Да, я получаю довольно схожую скорость, независимо от того, – user2320239

ответ

3

Основная проблема, которую я вижу здесь, заключается в том, что вы не распространяете свою работу, вы копируете ее через процессы. Таким образом, чем больше процессов вы получаете, тем больше работы вы выполняете в целом. На самом деле, наилучшим вариантом для вашего кода было бы иметь плоское время независимо от количества процессов MPI ...

Но так как ваш код делает очень мало вычислений для большого количества обращений к памяти (очень низкая арифметическая интенсивность), вы, скорее всего, связаны с памятью. Таким образом, увеличение количества процессов MPI (и общей рабочей нагрузки) увеличивает нагрузку на полосу пропускания памяти (которая является общим ресурсом по всем ядрам и последующим процессам MPI), то, что вы испытываете, вместо плоского времени увеличивает время. ..

Если у вас есть шанс увидеть какой-либо ускорение в вашем коде, вам придется фактически распределить работу вместо ее тиражирования. Это приведет к вычислению на ваших и bufferb данных, а не a и b (скважина a фактически здесь, что является еще одной ошибкой).

Смежные вопросы