当我在两台不同的机器上运行下面的代码时,我得到不同的输出,在一个输出中,输出是正确的(sum = sum2),在另一个输出中,输出不是正确的。
我不知道为什么
#include <stdio.h>
#include <math.h>
#include <omp.h>
int main(){
const int NX=1000;
const int NY=1000;
float x[NX+2];
float y[NX+2];
float u[NX+2][NY+2];
float x2; //
float y2;
float sum;
float sum2;
for (int i=0; i<NX+2; i++){
for (int j=0; j<NY+2; j++){
x2 = i;
y2 = j;
u[i][j] = x2+ y2;
sum += u[i][j];
}
}
for (int i=0; i<NX+2; i++){
#pragma omp parallel for
for (int j=0; j<NY+2; j++){
x2 = i;
y2 = j;
u[i][j] = x2+ y2;
}
}
for (int i=0; i<NX+2;i++){
for (int j=0; j<NY+2; j++){
sum2 += u[i][j];
}
}
printf("%f \n", sum);
printf("%f", sum2);
}
您需要初始化的值
float sum;
float sum2;
否则当操作:
sum += u[i][j];
和
sum2 += u[i][j];
导致不确定的行为。这就是为什么您看到两个不同的结果。
将两个变量都设置为零:
float sum = 0;
float sum2 = 0;
使用(至少)标志-Wall编译代码。如果这样做,将会看到以下警告:
main.c:17:7: warning: 'sum2' may be used uninitialized in this function [-Wmaybe-uninitialized]
17 | float sum2;
| ^~~~
main.c:16:7: warning: 'sum' may be used uninitialized in this function [-Wmaybe-uninitialized]
16 | float sum;
| ^~~
性能方面,而不是并行化内部循环:
for (int i=0; i<NX+2; i++){
#pragma omp parallel for
for (int j=0; j<NY+2; j++){
x2 = i;
y2 = j;
u[i][j] = x2+ y2;
}
}
您应该通过使用OpenMP折叠选项来描述当同时使两个循环并行时发生的情况
#pragma omp parallel for collapse(2)
for (int i=0; i<NX+2; i++){
for (int j=0; j<NY+2; j++){
u[i][j] = i + j;
}
}
即使该collapse
子句不是意见(例如,速度较慢),从性能角度来看,最好还是并行化外循环而不是内循环。首先,您避免了创建并行区域NX+2
时间的开销。其次,由于外部循环在列上进行迭代,内部循环在行上进行迭代,因此在线程之间划分第一个循环的迭代可减少错误共享的可能性。
此外,您还可以并行化其他两个循环。但是,您将需要使用OpenMP减少子句来避免在sum和sum2变量更新期间出现竞争情况。
最终代码如下所示:
#include <stdio.h>
#include <math.h>
#include <omp.h>
int main(){
const int NX=1000;
const int NY=1000;
float u[NX+2][NY+2];
float sum = 0;
float sum2 = 0;
#pragma omp parallel for reduction(+:sum)
for (int i=0; i<NX+2; i++){
for (int j=0; j<NY+2; j++){
sum += i+j;
}
}
#pragma omp parallel for
for (int i=0; i<NX+2; i++){
for (int j=0; j<NY+2; j++){
u[i][j] = i+j;
}
}
#pragma omp parallel for reduction(+:sum2)
for (int i=0; i<NX+2;i++){
for (int j=0; j<NY+2; j++){
sum2 += u[i][j];
}
}
printf("%f \n", sum);
printf("%f", sum2);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句