openMP reduce pragma错误的结果

时间:2014-09-12 09:36:26

标签: gcc openmp

我有这个代码已经工作了多年(并且在使用一些随机编译器时仍然有效)。

我们期望在顺序和并行执行中获得相同的结果。

症状是每次执行时,并行执行会产生另一个结果。

#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

它正在使用icc。

编辑:如果我们将优化-O3与Gcc一起使用,它也可以使用。

2 个答案:

答案 0 :(得分:1)

问题是你有一个嵌套循环,而pragma只适用于外层循环。您需要使用collapse子句。您可以在this questionthis site中了解它。如果您将#pragma行替换为:

,该程序可以正常运行
#pragma omp parallel for reduction(+:sum) collapse(2)

答案 1 :(得分: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];
    }
}

更改代码并在并行区域内定义ij

#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];
    }
}