Does gfortran help use DO CONCURRENT?

I am currently using gfortran 4.9.2, and I was wondering if the compiler really knows how to use the DO CONCURRENT construct (Fortran 2008). I know that the compiler "supports" it, but it is not clear what this means. For example, if automatic parallelization is enabled (with a certain number of specified threads), the compiler knows how to parallelize a parallel do loop?

Edit: As mentioned in the comment, this previous SO question is very similar to mine, but this is from 2012, and only the most recent versions of gfortran have implemented the latest features of modern Fortran, so I thought it was worth talking about the current state of the compiler in 2015 .

+9
source share
1 answer

Instead of explicitly including some new features, DO CONCURRENT in DO CONCURRENT seems to impose restrictions on the programmer to implicitly allow loop parallelization if necessary (using the -ftree-parallelize-loops=NPROC ).

Although a DO loop can contain any function call, the contents of DO CONCURRENT limited to PURE functions (i.e., it has no side effects). Therefore, when someone tries to use, for example, RANDOM_NUMBER (which is not PURE , because he needs to maintain the state of the generator) in DO CONCURRENT , DO CONCURRENT will protest:

 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 

Otherwise, DO CONCURRENT behaves as usual DO . It only forcibly uses parallelized code, so -ftree-parallelize-loops=NPROC succeeds. For example, in gfortran 9.1 and -fopenmp -Ofast -ftree-parallelize-loops=4 both the standard DO and F08 DO CONCURRENT in the following program run in 4 threads and with almost the same synchronization:

 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 
0
source

Source: https://habr.com/ru/post/986179/


All Articles