繁体   English   中英

顺序和并行版本给出不同的结果 - 为什么?

[英]Sequential and parallel versions give different results - Why?

我有一个嵌套循环:(L 和 A 是完全定义的输入)

    #pragma omp parallel for schedule(guided) shared(L,A) \
    reduction(+:dummy)
    for (i=k+1;i<row;i++){
            for (n=0;n<k;n++){
                #pragma omp atomic
                dummy += L[i][n]*L[k][n];
                L[i][k] = (A[i][k] - dummy)/L[k][k];
            }
            dummy = 0;
    }

及其顺序版本:

    for (i=k+1;i<row;i++){
            for (n=0;n<k;n++){
                dummy += L[i][n]*L[k][n];
                L[i][k] = (A[i][k] - dummy)/L[k][k];
            }
            dummy = 0;
    }

他们都给出不同的结果。 并行版本比顺序版本慢得多。

什么可能导致问题?

编辑:

为了摆脱原子指令引起的问题,我修改了代码如下:

#pragma omp parallel for schedule(guided) shared(L,A) \
    private(i)
    for (i=k+1;i<row;i++){
        double dummyy = 0;
        for (n=0;n<k;n++){
            dummyy += L[i][n]*L[k][n];
            L[i][k] = (A[i][k] - dummyy)/L[k][k];
        }
    }

但它也没有解决问题。 结果还是不一样。

我对 OpenMP 不太熟悉,但在我看来,您的计算与顺序无关。 即,将内循环的结果写入L[i][k] ,其中ik是内循环的不变量。 这意味着同一值在内循环中被覆盖k次,从而导致竞争条件。

此外, dummy似乎在不同线程之间共享,因此那里也可能存在竞争条件,除非您的 pragma 参数以某种方式阻止它。

总之,在我看来,如果您想要顺序执行给出的结果相同,则内部循环中的计算必须以相同的顺序执行。 因此只有外部循环可以并行化。

在您的并行版本中,您插入了一个不必要的(并且可能有害的)原子指令。 一旦您将dummy声明为缩减变量,OpenMP 就会负责停止干扰缩减的线程。 我认为不必要的指令的主要影响是大大降低了代码速度。

我看到您有另一个解决结果错误的答案。 但是我注意到你似乎在每次外循环迭代结束时将dummy设置为0 ,如果你试图将它用作某种累加器,这似乎很奇怪,这就是 reduction 子句所建议的。 也许您想减少内部循环的dummy

如果您在还原方面遇到问题,请阅读此

结果的差异来自内部循环变量n ,它在线程之间共享,因为它是在 omp pragma 之外定义的。

澄清:循环变量n应该在 omp pragma 中声明,因为它应该是特定于线程的,例如for (int n = 0;.....)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM