Arrays 简单DO循环的自动并行化-内存引用太复杂
我正在使用Absolft pro Fortran,我有一段代码如下:Arrays 简单DO循环的自动并行化-内存引用太复杂,arrays,parallel-processing,fortran,fortran90,Arrays,Parallel Processing,Fortran,Fortran90,我正在使用Absolft pro Fortran,我有一段代码如下: program test1 INTEGER :: q, CAPQ, ingrid(1:6), outgrid(1:10) ingrid = (/1,2,3,4,5,6/) outgrid = 0 CAPQ = 6 DO q=1,CAPQ outgrid(q) = ingrid(q) ENDDO END 但是,当我构建它时,它不会自动并行化,因为: 具有索引变量Q的循环无法并行化,因为它包含一个间接内存引用
program test1
INTEGER :: q, CAPQ, ingrid(1:6), outgrid(1:10)
ingrid = (/1,2,3,4,5,6/)
outgrid = 0
CAPQ = 6
DO q=1,CAPQ
outgrid(q) = ingrid(q)
ENDDO
END
但是,当我构建它时,它不会自动并行化,因为:
具有索引变量Q的循环无法并行化,因为它包含一个间接内存引用,该引用太复杂,无法成功分析
但这是一个非常简单的内存访问,我只是从数组中调用这个数字,然后将它放入另一个数组中。它的出现顺序应该无关紧要,因此可以并行化。我不熟悉Absolft Fortran,但我可以告诉你,我还没有找到一个在自动并行化方面做得很好的编译器。无论如何,这是一项困难的任务,我不会屏住呼吸等待一个编译器能够并行化代码,甚至接近您自己可以实现的目标。我强烈建议您考虑使用OpenMP(或者您可以选择的任何并行化库)并行化代码。这并不困难,而且确实是值得的,特别是如果并行化代码的“瓶颈”。在这个特定的示例中,代码可以很容易地并行化为
program test1
use omp_lib
implicit none
integer :: q, CAPQ, ingrid(1:6), outgrid(1:6)
ingrid=(/1,2,3,4,5,6/)
outgrid=0
CAPQ=6
!$omp parallel do private(q)
do q=1,CAPQ
outgrid(q)=ingrid(q)
print "(2(a,i0))","q=",q," processed by thread ",omp_get_thread_num()
end do
!$omp end parallel do
end program test1
注意,我添加了一个print
语句来验证可执行文件是否确实并行运行do循环。编译并运行带有和不带这两个的示例#omp
语句以查看差异。启用并行化后,您应该看到如下内容
q=6 processed by thread 5
q=4 processed by thread 3
q=5 processed by thread 4
q=2 processed by thread 1
q=3 processed by thread 2
q=1 processed by thread 0
如果禁用并行化,线程应该处处为零
上面的示例在gfortran中,必须使用-fopenmp指令编译。
根据您使用的编译器的不同,可能需要用类似的语句替换语句
use omp_lib
,编译器指令也可能略有不同。根据我在网上找到的Absolft Pro Fortran用户指南,编译器指令是-openmp。《用户指南》还提到了“积极的OpenMP”并行化选项,这些选项绝对值得一看。编译器必须避免并行化,因为线程之间的存储距离不超过128字节,这将导致错误共享。有没有办法解决这一问题,为了不禁止并行化?我删除了对OpenMP的引用:OpenMP不包括自动并行化,并且我找不到Absolft pro使用OpenMP进行自动并行化的引用。如果您认为它真的与OpenMP有关,请澄清。@tim18您能再解释一下您的意思吗?以及如何避免这种情况。非常感谢。如果打算使用OpenMP,则需要一些OpenMP指令。我会在propgram之后和缺少的隐式none之前使用OMP。为了避免误解,并行化do循环并不总是像Laurence_jj发布的测试示例那样简单。我可以想象do循环中的实际代码要比简单赋值复杂得多(你可以通过移除do循环并用一个简单的outgrid(1:CAPQ)=ingrid(1:CAPQ)
替换它)。根据循环中的内容,可能需要特别注意,包括其他OpenMP功能。更糟糕的是:在某些情况下,do循环根本无法并行化。