gfortran是否利用DO CONCURRENT?

时间:2015-04-28 19:32:21

标签: parallel-processing fortran gfortran

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

编辑:正如评论中提到的,this previous question上的SO与我的非常相似,但它是从2012年开始的,只有最新版本的gfortran才能实现现代Fortran的最新功能,所以我认为它值得询问2015年编译器的当前状态。

1 个答案:

答案 0 :(得分:0)

gfortran中的DO CONCURRENT并没有显式启用某些新功能,而是对程序员施加了限制,以便隐式在需要时允许循环并行化(使用选项-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

否则,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