gfortran是否利用DO CONCURRENT的优势?

15
我目前使用的是gfortran 4.9.2,我想知道编译器是否真正知道如何利用DO CONCURRENT结构(Fortran 2008)。我知道编译器“支持”它,但这并不清楚。例如,如果自动并行化被打开(指定了一些线程数),编译器是否知道如何并行化do concurrent循环?
编辑:如评论所述,这个之前的问题在SO上非常类似于我的问题,但它是在2012年,只有非常最新版本的gfortran才实现了现代Fortran的最新功能,因此我认为问一下2015年编译器的当前状态是值得的。

4
请参阅 https://gcc.gnu.org/ml/fortran/2014-02/msg00077.html。 - Vladimir F Героям слава
好的,看起来答案是“不”。 - Christopher A. Wong
1
你可以使用带有OpenMP的普通DO循环来实现相同的效果。 - Jeff Hammond
@Jeff 我不会称之为相同的效果。你可以实现并行循环。使用do concurrent可能有助于编译器在某些情况下执行矢量化,即使是非线程程序,尽管引用的邮件表明这种情况不太常见。它还可以帮助自动并行化,如果并行器对普通do循环存在一些依赖关系的话。奇怪的是,你不能混合使用OpenMP和do concurrent,所以我通常只使用OpenMP和普通的do循环。 - Vladimir F Героям слава
此外,我想看到证据表明do concurrent比带有OpenMP fordo更能实现编译器自动向量化。我已经花了相当多的时间研究编译器自动向量化,而do concurrent并不能解决对齐问题。Fortran语义已经确保了反别名和OpenMP for意味着循环独立,那么你认为从do concurrent中还能得到什么? - Jeff Hammond
显示剩余5条评论
1个回答

12
与明确启用一些新功能不同,gfortran 中的 DO CONCURRENT 似乎会对程序员施加一些限制,以便在需要时隐式地允许循环并行化(使用选项 -ftree-parallelize-loops=NPROC)。 DO 循环可以包含任何函数调用,而 DO CONCURRENT 的内容仅限于 PURE 函数(即没有副作用)。因此,当尝试在 DO CONCURRENT 中使用例如 RANDOM_NUMBER(它不是 PURE,因为它需要维护生成器状态)时,gfortran 会发出警告。
prog.f90:25:29:

   25 |         call random_number(x)
      |                             1
Error: Subroutine call to intrinsicrandom_numberin DO CONCURRENT block at (1) is not PURE

否则,DO CONCURRENT的行为就像普通的DO。它仅强制使用可并行化的代码,以便-ftree-parallelize-loops=NPROC成功运行。例如,使用gfortran 9.1和-fopenmp -Ofast -ftree-parallelize-loops=4,以下程序中的标准DO和F08 DO CONCURRENT循环都在4个线程中运行,并且时间几乎相同:
program test_do

    use omp_lib, only: omp_get_wtime

    integer, parameter :: n = 1000000, m = 10000
    real,  allocatable :: q(:)

    integer :: i
    real    :: x, t0

    allocate(q(n))

    t0 = omp_get_wtime()
    do i = 1, n
        q(i) = i
        do j = 1, m
            q(i) = 0.5 * (q(i) + i / q(i))
        end do
    end do
    print *, omp_get_wtime() - t0

    t0 = omp_get_wtime()
    do concurrent (i = 1:n)
        q(i) = i
        do j = 1, m
            q(i) = 0.5 * (q(i) + i / q(i))
        end do
    end do
    print *, omp_get_wtime() - t0

end program test_do

1
当我使用gfortran -O3或-Ofast和-ftree-parallelize-loops = 4运行您的程序时,它经常会打印负时间。有什么想法吗?据我所知,omp_get_wtime()未在循环内调用,因此似乎应该返回正确且一致的时间。我确实看到程序使用多个处理器,因此openmp和gfortran并行化正在工作。奇怪。 - Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接