I've opened PRs for both of these issues: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110547
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110548 -Andrew -- * Andrew Benson: http://users.obs.carnegiescience.edu/abenson * Galacticus: https://github.com/galacticusorg/galacticus On Wed, Jun 28, 2023, 5:01 PM Andrew Benson <aben...@carnegiescience.edu> wrote: > 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 > > > >