Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parallel processing 如何删除Fortran竞态条件?_Parallel Processing_Fortran_Openmp_Race Condition - Fatal编程技术网

Parallel processing 如何删除Fortran竞态条件?

Parallel processing 如何删除Fortran竞态条件?,parallel-processing,fortran,openmp,race-condition,Parallel Processing,Fortran,Openmp,Race Condition,原谅我,如果这不是一个真正的比赛条件;我对命名法不太熟悉 我遇到的问题是,启用OpenMP时,此代码运行较慢。我认为循环应该足够大(k=100000),所以我认为开销不是问题 据我所知,这里出现了竞争条件,因为所有的循环都在试图访问相同的v(I,j)值,从而降低了代码的速度 这里的最佳修复方法是创建与线程数量相同的v()数组副本,并让每个线程访问不同的副本吗 我在16核上使用英特尔编译器,它的运行速度比单核稍慢。 谢谢大家 !$OMP PARALLEL DO Do 500, k=1,n Do

原谅我,如果这不是一个真正的比赛条件;我对命名法不太熟悉

我遇到的问题是,启用OpenMP时,此代码运行较慢。我认为循环应该足够大(k=100000),所以我认为开销不是问题

据我所知,这里出现了竞争条件,因为所有的循环都在试图访问相同的v(I,j)值,从而降低了代码的速度

这里的最佳修复方法是创建与线程数量相同的v()数组副本,并让每个线程访问不同的副本吗

我在16核上使用英特尔编译器,它的运行速度比单核稍慢。 谢谢大家

!$OMP PARALLEL DO

Do 500, k=1,n

Do 10, i=-(b-1),b-1
 Do 20, j=-(b-1),b-1
 if (abs(i).le.l.and.abs(j).eq.d) then
    cycle
 endif
 v(i,j)=.25*(v(i+1,j)+v(i-1,j)+v(i,j+1)+v(i,j-1))

 if (k.eq.n-1) then
    vtest(i,j,1)=v(i,j)
endif
if (k.eq.n) then
    vtest(i,j,2)=v(i,j)
endif
 20 continue
10 continue

500 continue

!$OMP END PARALLEL DO

虽然我不确定这是否是你的程序不能更快执行的原因,但你肯定已经编程了一个竞赛条件。这条线

v(i,j)=.25*(v(i+1,j)+v(i-1,j)+v(i,j+1)+v(i,j-1))
这将由所有线程针对
i
j
的相同(一组)值执行,这是比赛发生的地方。假设您的程序不协调对
v
元素的读写,那么实际上,您的程序是不确定的,因为无法知道对
v
进行更新的顺序

您应该在检查程序结果时注意到这种不确定性,并且注意到更改线程数也会对结果产生影响。然后,通过对阵列执行长时间运行的模具操作,结果可能会收敛到相同(或足够相似)的值

OpenMP为您提供了协调变量访问的工具,但它不会自动实现这些工具;引擎盖下绝对没有任何东西可以阻止对
v
的准同步读写。因此,缺乏绩效改进的原因在于其他方面。这可能是由于多个线程在系统内存层次结构的某个级别上对缓存的影响。一个串行程序在内存顺序中对数组的每一个元素进行一次友好的、缓存友好的运行,就缓存而言,这将成为对内存的大量随机访问,每次都需要访问RAM

有可能是别的原因造成的。如果执行OpenMP版本的时间略长于执行串行版本的时间,我怀疑该程序实际上不是并行执行的。未能正确编译是导致这种情况的一个常见原因

如何解决这个问题

OpenMP在一个数组中的常见模式是在一个数组索引上并行。声明

!$omp parallel do
do i=-(b-1),b-1
....
end do
确保每个线程为
i
获取一组不同的值,这意味着它们写入
v
的不同元素,从而消除(几乎)数据争用。在编写程序时,每个线程都会获得一组不同的值
k
,但在内部循环中没有使用(很多)

顺便说一下,测试

if (k==n-1) then

在每一次迭代中,看起来您都在为您的程序绑定一个锚,为什么不呢

do k=1,n-2
并在循环结束时处理对
vtest
的更新

你可以分开
$omp并行执行类似的操作

!$omp parallel
do k=1,n-2

    !$omp do
    do i=-(b-1),b-1
(并在并行循环和区域的末尾进行相应的更改)。现在,所有线程都执行并行区域的全部内容,但每个线程都有自己的
i
值集要使用。我建议您在指令中添加子句,以指定每个变量的可访问性(例如
private
shared
);但是这个答案有点太长了,我将不详细讨论这些问题。或使用
附表
条款

最后,当然,即使有我建议的更改,您的程序也将是不确定的,因为

v(i,j)=.25*(v(i+1,j)+v(i-1,j)+v(i,j+1)+v(i,j-1))
将从另一个线程更新的
v
中读取相邻元素(在您无法控制的时间)。为了解决这个问题。。。我得回去工作了

v(i,j)=.25*(v(i+1,j)+v(i-1,j)+v(i,j+1)+v(i,j-1))