I've been starting to try using OpenMP task parallelism, but I'm running into some issues. I'm not sufficiently experienced with task parallelism in OpenMP to know if I'm misunderstanding how it should work, or if there's a compiler bug.
Here's an example code (highly simplified from the actual code I'm working on): module taskerMod type :: tasker integer :: depth=-1 contains final :: taskerDestruct procedure :: compute => taskerCompute end type tasker contains subroutine taskerDestruct(self) !$ use :: OMP_Lib implicit none type(tasker), intent(inout) :: self write (0,*) "DESTRUCT FROM DEPTH ",self%depth !$ ," : ",omp_get_thread_num() return end subroutine taskerDestruct recursive subroutine taskerCompute(self) !$ use :: OMP_Lib implicit none class(tasker), intent(inout) :: self !$omp atomic self%depth=self%depth+1 write (0,*) "DEPTH ",self%depth !$ ," : ",omp_get_thread_num() if (self%depth < 3) then !$omp task untied call self%compute() !$omp end task end if return end subroutine taskerCompute end module taskerMod program testTasks use :: taskerMod implicit none type(tasker) :: tasker_ tasker_=tasker(0) !$omp parallel !$omp single !$omp taskgroup !$omp task untied call tasker_%compute() !$omp end task !$omp end taskgroup !$omp end single !$omp end parallel end program testTasks Compiling without OpenMP results in the expected behavior: $ gfortran test.F90 $ ./a.out DESTRUCT FROM DEPTH -1 DEPTH 1 DEPTH 2 DEPTH 3 There's a call to the finalizer for the tasker class (on assignment), and then it simply reports the 3 levels of recursion that I've set it to go through. But, if I compile with OpenMP and run just a single thread (the same problem occurs with multiple threads also): $ gfortran test.F90 -fopenmp $ ./a.out DESTRUCT FROM DEPTH -1 DEPTH 1 DEPTH 2 DESTRUCT FROM DEPTH 2 DEPTH 3 DESTRUCT FROM DEPTH 3 I now see calls to the finalizer from the 2nd and 3rd recursive calls to the taskerCompute function. Since self is intent(inout) to this function I wouldn't expect it to be finalized. But, this is where I doubt my understanding of how tasks should behave. This happens with versions 12.0.0, 13.0.1, and the current HEAD of the GCC git repo. But, ifort, does not produce the extra finalizer calls when used to compile the above with OpenMP. Does anyone have any insights into whether or not the finalizer should be called in this situation? Another issue I find with a modified version of the above: module taskerMod type :: helper end type helper type :: tasker integer :: depth=-1 contains final :: taskerDestruct procedure :: compute => taskerCompute end type tasker contains subroutine taskerDestruct(self) !$ use :: OMP_Lib implicit none type(tasker), intent(inout) :: self write (0,*) "DESTRUCT FROM DEPTH ",self%depth !$ ," : ",omp_get_thread_num() return end subroutine taskerDestruct recursive subroutine taskerCompute(self,helper_) !$ use :: OMP_Lib implicit none class(tasker), intent(inout) :: self class(helper), intent(inout), optional :: helper_ !$omp atomic self%depth=self%depth+1 write (0,*) "DEPTH ",self%depth !$ ," : ",omp_get_thread_num() if (self%depth < 3) then !$omp task untied call self%compute(helper_) !$omp end task end if return end subroutine taskerCompute end module taskerMod program testTasks use :: taskerMod implicit none type(tasker) :: tasker_ type(helper) :: helper_ tasker_=tasker(0) !$omp parallel !$omp single !$omp taskgroup !$omp task untied call tasker_%compute() !$omp end task !$omp end taskgroup !$omp end single !$omp end parallel end program testTasks This one causes a segfault: $ gfortran test1.F90 -fopenmp $ ./a.out DESTRUCT FROM DEPTH -1 DEPTH 1 Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 0x2ac99289a1ef in ??? #1 0x401840 in ??? #2 0x2ac9925a9606 in GOMP_task at ../../../gcc-git/libgomp/task.c:644 #3 0x401588 in ??? #4 0x40197b in ??? #5 0x2ac9925a77a4 in gomp_barrier_handle_tasks at ../../../gcc-git/libgomp/task.c:1650 #6 0x2ac9925b058f in gomp_team_barrier_wait_end at ../../../gcc-git/libgomp/config/linux/bar.c:116 #7 0x2ac9925aeffc in gomp_team_end at ../../../gcc-git/libgomp/team.c:956 #8 0x401692 in ??? #9 0x4016cd in ??? #10 0x2ac992886d0c in ??? #11 0x401128 in ??? Segmentation fault This appears to be due to the optional argument, helper_. If it is present in the initial call, i.e.: call tasker_%compute(helper_) then this runs without a segfault. -Andrew -- * Andrew Benson: https://abensonca.github.io * Galacticus: https://github.com/galacticusorg/galacticus