Desde o OpenMP 4.5, arrays podem ser reduzidos usando pragmas. Mas, eu enfrentei um problema quando tentei usá-lo em arrays de tipo derivado porque !$OMP DECLARE REDUCTION não foi encontrado para este tipo. Eu entendo o problema. Depois de muitas tentativas, eu finalmente encontrei um programa que parece funcionar. Este é o código:
O módulo ( module.f90
):
module my_mod
implicit none
type :: my_type_t
integer :: x
integer :: y
end type my_type_t
interface operator(+)
module procedure add_my_type_t_vec
end interface
!$OMP DECLARE REDUCTION (+ : my_type_t : omp_out = omp_out + omp_in) INITIALIZER (omp_priv = omp_orig)
contains
function add_my_type_t_vec(a,b) result(res)
type(my_type_t), dimension(:),intent(in) :: a, b
type(my_type_t), dimension(size(a)) :: res
res(:)%x = a(:)%x + b(:)%x
res(:)%y = a(:)%y + b(:)%y
end function add_my_type_t_vec
end module my_mod
E o programa ( pgm.f90
) que o utiliza:
program parallel
use omp_lib
use my_mod
implicit none
type(my_type_t), dimension(:), allocatable :: private_var, shared_var
integer :: i
allocate(private_var(5), shared_var(5))
shared_var%x=0
shared_var%y=0
!$OMP PARALLEL NUM_THREADS(4) PRIVATE(private_var,i) REDUCTION (+ : shared_var)
!$OMP DO
do i=1,1000
private_var%x = 1
private_var%y = 2
shared_var = shared_var + private_var
end do
!$OMP END DO
!$OMP END PARALLEL
print *, "Total : ", shared_var
end program parallel
Compilação com:gfortran -fopenmp module.f90 pgm.f90
Para encontrar essa solução, usei a seguinte resposta https://stackoverflow.com/a/61148205/7462275 .
Funciona, mas não tenho certeza de que não terei comportamento indefinido em certas circunstâncias. E não entendo completamente a sintaxe e o mecanismo dos pragmas DECLARE REDUCTION e INITIALIZER. De fato, fiz uma cópia/colagem da resposta mencionada acima e não há explicação nela. Obrigado pelos conselhos e explicações.