2014-09-12 3 views
0

У меня есть этот код, который работал много лет (и по-прежнему работает при использовании некоторых случайных компиляторов).Неверный результат с openMP reduction pragma

То, что мы ожидаем, должно иметь тот же результат в последовательном и параллельном исполнении.

Симптом заключается в том, что при каждом выполнении параллельное выполнение дает другой результат.

#include <omp.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) 
{ 

    int i, N, j, sum; 
    int ** A; 

    sum=0; 
    N=1000; 

    A=(int**)malloc(N*sizeof(int*)); 
    for (i=0;i<N;i++) { 
     A[i] = (int*)malloc(N *sizeof(int)); 
    } 

    for (i=0; i<N; ++i) { 
     for (j=0; j<N; ++j) { 
      A[i][j]=i+j; 
      sum+=A[i][j]; 
     } 
    } 

    printf("Total sum = %d \n",sum); 
    sum=0; 


    #pragma omp parallel for reduction(+:sum) 
    for (i=0; i<N; ++i) { 
     for (j=0; j<N; ++j) { 
      sum += A[i][j]; 
     } 
    } 

    printf("Total sum = %d \n",sum); 

    for (i=0;i<N;i++){ free(A[i]);} 
    free(A); 

    return 0; 
} 

Мы скомпилировать его так:

gcc -fopenmp reduction.c 

И запустить его так:

./a.out 
Total sum = 999000000 
Total sum = 822136991 

Он работает с МЦХ.

Редактировать: если мы используем оптимизацию -O3 с Gcc, она также работает.

+1

Используйте этот '#pragma OMP параллельно для восстановления (+: сумма) частное (J)'. –

+0

@ Zboson спасибо, кажется правильным. Если вы создадите ответ, я приму его. –

ответ

1

Вот три способа исправить код

Явное сделать j частный

#pragma omp parallel for reduction(+:sum) private(j) 
for (i=0; i<N; ++i) { 
    for (j=0; j<N; ++j) { 
     sum += A[i][j]; 
    } 
} 

Изменить код и определить i и j внутри параллельной области

#pragma omp parallel reduction(+:sum) 
{ 
    int i,j; 
    #pragma omp for 
    for (i=0; i<N; ++i) { 
     for (j=0; j<N; ++j) { 
      sum += A[i][j]; 
     } 
    } 
} 

Использование C99 (или GNU99) и изменить свой код

#pragma omp parallel for reduction(+:sum) 
for (int i=0; i<N; ++i) { 
    for (int j=0; j<N; ++j) { 
     sum += A[i][j]; 
    } 
} 
1

Проблема в том, что у вас есть вложенный цикл, а прагма применяется только к внешнему. Вам необходимо использовать предложение collapse. Вы можете прочитать об этом this question и в this site. Программа корректно работает, если вы замените #pragma линию:

#pragma omp parallel for reduction(+:sum) collapse(2) 
+2

Или он мог просто сделать 'j' частным. –

+0

@ Zboson правда, что – jdehesa

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