C OpenMP循环每次给出不同的结果

C OpenMP循环每次给出不同的结果,c,multithreading,parallel-processing,openmp,reduction,C,Multithreading,Parallel Processing,Openmp,Reduction,串行输出 ------------------0.013850 0.030408 -0.130364 0.107690 0.061082 0.023526 0.066983 -0.030821 -0.024117 0.037548 0.000000 我不知道我在哪里出错,但我在并行程序中得到了不同的结果。它每次都给出不同的输出。 还有一个问题,即当我从顶部删除#pragma omp parallel时,我得到了正

串行输出

 ------------------0.013850
    0.030408
    -0.130364
    0.107690
    0.061082
    0.023526
    0.066983
    -0.030821
    -0.024117
    0.037548
    0.000000
我不知道我在哪里出错,但我在并行程序中得到了不同的结果。它每次都给出不同的输出。 还有一个问题,即当我从顶部删除
#pragma omp parallel
时,我得到了正确的值,但没有时间优势。我必须添加
#pragma omp parallel

所以需要一些解决方案。

正如@1201programalam所建议的,你有一场数据竞赛。它涉及平行区域内和临界截面外的这一陈述:

-0.013813
-0.028405
-0.044722
-0.064258
-0.087550
-0.072226
-0.062273
-0.055638
-0.052620
0.000000
每个线程在每次迭代中都执行该值,并且每个线程也会读回该值。读操作在临界区内并不能避免数据竞争——写操作也需要在临界区内(不一定是同一个),或者受到某种同步的保护,以避免数据竞争

但这里的问题如此之大,以至于数据竞争几乎无关紧要。主要问题是循环迭代之间的计算具有很强的数据依赖性。也就是说,当连续运行时,外部循环的每次迭代都会根据上一次迭代中计算的值更新
ex
hy
的所有元素。无论同步的程度如何,或者关键原因的范围有多广,如果允许以不同的顺序执行外循环迭代,那么就不能期望相同的结果(甚至一致的结果),就像并行化一样


这里值得庆幸的是,并行化并没有给您带来多少好处,因为几乎所有由外部循环执行的工作都在关键部分。只要删除
omp parallel
omp critical
指令,就可以大大改进此代码。对于这样的小<代码> KE/COD>以及这样简单的计算,将内码<代码OMP留给S也没有什么意义,但是如果<代码> KE>代码>大得多,那么你可以考虑留下内部循环的并行化。

作为@ 1201StaltCudio建议,你有一个数据竞赛。它涉及平行区域内和临界截面外的这一陈述:

-0.013813
-0.028405
-0.044722
-0.064258
-0.087550
-0.072226
-0.062273
-0.055638
-0.052620
0.000000
每个线程在每次迭代中都执行该值,并且每个线程也会读回该值。读操作在临界区内并不能避免数据竞争——写操作也需要在临界区内(不一定是同一个),或者受到某种同步的保护,以避免数据竞争

但这里的问题如此之大,以至于数据竞争几乎无关紧要。主要问题是循环迭代之间的计算具有很强的数据依赖性。也就是说,当连续运行时,外部循环的每次迭代都会根据上一次迭代中计算的值更新
ex
hy
的所有元素。无论同步的程度如何,或者关键原因的范围有多广,如果允许以不同的顺序执行外循环迭代,那么就不能期望相同的结果(甚至一致的结果),就像并行化一样


这里值得庆幸的是,并行化并没有给您带来多少好处,因为几乎所有由外部循环执行的工作都在关键部分。只要删除
omp parallel
omp critical
指令,就可以大大改进此代码。对于这样的小<代码> KE/COD>以及这样简单的计算,将内码<代码OMP留给S也没什么意义,但是如果<代码> KE>代码>大得多,那么你可以考虑留下内部循环的并行化。

并行运行时不同的结果是一个很大的指标,表明你有数据竞赛。您还可以访问超出范围的数组(因为
ex[KE]
已经过了最后一步,您的for循环应该一直运行到
。首先,我非常感谢您的帮助。但我仍然得到了相同的问题并行运行时的不同结果是您存在数据竞争的一个重要指标。您还可以访问超出范围的数组(因为
ex[KE]
已经过了终点,你的for循环应该一直运行到
首先我非常感谢你的帮助。但我还是得到了同样的问题我得到了错误,这就是为什么我要取KE 10,但实际上我必须取KE 10000和nsteps 1000000。如果取KE那么多。还有一件事,你在这里告诉我的,外部循环将在不同的顺序,我该怎么做。#########如果删除pragma omp parallel,那么我会得到正确的输出,但是并行化不是那么有效,没有时间优势。@Akilakumargouda,线程管理会带来不小的开销,内部循环中的计算非常简单。
KE
10000可能足以使e内部循环的并行化是值得的,但同样,可能不值得。请进行测试。
NSTEPS
的大小是不相关的,因为计算中涉及的数据依赖性使得外部循环的并行化不可行,正如这个答案已经讨论过的。如果删除所有并行化语法,那么它就是我的串行代码。我的las我不会问你有没有其他方法来并行这段代码。@AKHILAKUMARGOUDA,是的,可能是串行版本是你能做的最好的。这段代码看起来像某种动力学计算,每个状态都是根据前一个状态计算的,所以在计算nex之前必须计算每个状态也就不足为奇了t一——这是连续的。正如我已经说过的,对于10000的
KE
,你可能会看到内部循环并行化的一些改进。也许这足够值得一试,所以至少值得一试。我得到了一个错误,这就是为什么我取KE 10,但实际上我必须取KE 10000和nsteps 1000000。如果取KE那么多。以及还有一件事
            ex[kc] = pulse;