gfortran是否利用DO CONCURRENT?

Chr*_*ong 9 parallel-processing fortran gfortran

我目前正在使用gfortran 4.9.2,我想知道编译器是否真的知道如何利用DO CONCURRENT构造(Fortran 2008).我知道编译器"支持"它,但不清楚它是什么.例如,如果打开自动并行化(指定了一定数量的线程),编译器是否知道如何并行化并发循环?

编辑:正如评论中提到的,关于SO的前一个问题与我的非常相似,但它是从2012年开始的,只有最新版本的gfortran已经实现了现代Fortran的最新功能,所以我认为值得询问2015年编译器的当前状态.

jac*_*cob 8

与其显式启用某些新功能,DO CONCURRENTgfortran 似乎对程序员施加了限制,以便在需要时隐式允许循环并行化(使用选项-ftree-parallelize-loops=NPROC)。

虽然DO循环可以包含任何函数调用,但其内容DO CONCURRENT仅限于PURE函数(即,没有副作用)。因此,当有人尝试在 中使用例如RANDOM_NUMBER(这不是PURE因为它需要维护生成器的状态)时DO CONCURRENT,gfortran 会抗议:

prog.f90:25:29:

   25 |         call random_number(x)
      |                             1
Error: Subroutine call to intrinsic ‘random_number’ in DO CONCURRENT block at (1) is not PURE
Run Code Online (Sandbox Code Playgroud)

否则,DO CONCURRENT表现正常DO。它只强制使用可并行化的代码,因此-ftree-parallelize-loops=NPROC成功。例如,使用 gfortran 9.1 和-fopenmp -Ofast -ftree-parallelize-loops=4,以下程序中的标准DO和 F08DO 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
Run Code Online (Sandbox Code Playgroud)