标量代码和并行代码的不同行为

Different behaviour between scalar and parallel code

本文关键字:代码 并行 标量      更新时间:2023-10-16

我想知道为什么以下代码在其标量和并行变体中产生不同的结果:

#define N 10
double P[N][N];
// zero the matrix just to be sure...
for (int i=0; i<N; i++)
    for(int j=0; j<N; j++)
        P[i][j]=0.0;

double xmin=-5.0,ymin=-5.0,xmax=5.0,ymax=5.0;
double x=xmin,y=ymin;
double step= abs(xmax-xmin)/(double)(N - 1 );
for (int i=0; i<N; i++)
{
    #pragma omp parallel for ordered schedule(dynamic)
    for ( int j=0; j<N; j++)
    {
        x = i*step+xmin;
        y = j*step+ymin;
        P[i][j]=x+y;
    }
}

这段代码在两个版本中产生的结果并不完全相同(标量版本只注释掉了#pragma ...部分)。我注意到的是,并行版本中P[i][j]的元素中有很小一部分与标量版本的元素不同,但我想知道为什么…

按照建议将#pragma放在外环是一团糟…完全错误的结果。

注:linux

啊,现在我看到问题了。你对最后一个问题的评论没有足够的背景让我理解。但现在很清楚了。

问题在这里:

    x = i*step+xmin;
    y = j*step+ymin;

xy被声明在并行区域之外,因此它们被所有线程共享。(因此在所有线程之间出现了一个令人讨厌的竞争状态…)

要解决这个问题,将它们设置为本地:

for ( int j=0; j<N; j++)
{
    double x = i*step+xmin;
    double y = j*step+ymin;
    P[i][j]=x+y;
}

通过这个修复,您应该能够将#pragma放在外部循环而不是内部循环上。