我有这个代码已经工作了多年(并且在使用一些随机编译器时仍然有效)。
我们期望在顺序和并行执行中获得相同的结果。
症状是每次执行时,并行执行会产生另一个结果。
#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一起使用,它也可以使用。
答案 0 :(得分:1)
问题是你有一个嵌套循环,而pragma只适用于外层循环。您需要使用collapse
子句。您可以在this question和this 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];
}
}
更改代码并在并行区域内定义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];
}
}