Building on Week 5’s work with the TASK construct and fixes for shared/private variables, Week 6 focused on making shared variables work reliably in the TASK construct and adding the TASKWAIT construct. Last week, I planned to enhance TASK support and implement teams, but debugging TASK issues took priority. This week, I made PR #7905, and spent about 25 hours tackling these challenges through careful debugging and implementation.
Debugging and Fixing TASK Construct Issues
This week, I worked on ensuring shared variables function correctly in the TASK construct, a task that proved more complex than expected. I faced multiple segfaults and struggled to pinpoint the cause, eventually realizing it was a mix of two or three bugs. To tackle this, I took a step-by-step approach, starting from scratch by writing lowered Fortran code with GOMP calls for TASK. This revealed the first issue: the task data struct size sent to GOMP_TASK was incorrect, causing segfaults. The second problem was that shared variables in OMPRegion had garbage initial values. Debugging the LLVM IR showed that c_f_pointer was using the address of the struct member instead of its value for non-array shared variables, leading to junk data.
Implementation Details and Fixes in PR #7905
In PR #7905, I addressed these issues to support shared variables in the TASK construct and implemented the TASKWAIT construct, contributing to Issue #7332 and Issue #7365 while fixing Issue #7904. I corrected the task data struct size calculation for GOMP_TASK calls and fixed the c_f_pointer issue in asr_to_llvm.cpp by ensuring it references the correct memory address for non-array shared variables. This required debugging of the LLVM IR to identify all failure scenarios. Additionally, I added TASKWAIT to synchronize tasks, ensuring proper execution flow.
Examples: TASK and TASKWAIT Constructs
Below are the MREs from PR #7905 that demonstrate the improved TASK construct with shared variables and the new TASKWAIT construct.
View MRE for TASK with Pointers (bindc5.f90)
1module thread_data_module_tasks
2 use, intrinsic :: iso_c_binding
3 implicit none
4 type :: thread_data
5 type(c_ptr) :: i_ptr
6 end type thread_data
7end module thread_data_module_tasks
8
9program bindc5
10 use thread_data_module_tasks
11 use, intrinsic :: iso_c_binding
12 implicit none
13 integer, target :: i
14 integer, pointer :: ptr_i, ptr_i2
15 type(thread_data), pointer :: d,d1
16 type(thread_data), target :: threadData, taskData
17 type(c_ptr) :: threadPtr, taskPtr
18
19 i=0
20
21 threadData%i_ptr = c_loc(i)
22 threadPtr = c_loc(threadData)
23 call c_f_pointer(threadPtr, d)
24 call c_f_pointer(d%i_ptr, ptr_i)
25
26 ptr_i=2
27
28 taskData%i_ptr = d%i_ptr
29 taskPtr = c_loc(taskData)
30 call c_f_pointer(taskPtr, d1)
31 call c_f_pointer(d1%i_ptr, ptr_i2)
32
33 ptr_i2=3
34
35 print*, i,ptr_i2,ptr_i
36 if(i/=ptr_i2 .and. i/=ptr_i) error stop
37end program bindc5View MRE for TASK with Shared Counter (openmp_55.f90)
1program openmp_55
2 use omp_lib
3 implicit none
4 integer :: i,n=10,counter
5 call omp_set_num_threads(8)
6counter=0
7 !$OMP PARALLEL
8 !$OMP MASTER
9 do i = 1, n
10 !$OMP TASK shared(counter)
11 counter=counter+1
12 print *, "Task Done by TID:-",omp_get_thread_num()
13 !$OMP END TASK
14 end do
15 !$OMP END MASTER
16 !$OMP END PARALLEL
17 if(counter/=10) error stop
18end program openmp_55View MRE for TASK with Shared Counter (openmp_56.f90)
1program openmp_56
2 use omp_lib
3 implicit none
4 integer :: counter
5 counter=0
6 call omp_set_num_threads(10)
7
8 !$omp parallel
9 !$omp task shared(counter)
10 counter=counter+1
11 print *, "Task done by TID:-",omp_get_thread_num()
12 !$omp end task
13 !$omp end parallel
14 if(counter/=10) error stop
15end program openmp_56View MRE for TASK with TASKWAIT (openmp_57.f90)
1program openmp_57
2 use omp_lib
3 implicit none
4 integer, parameter :: N = 5
5 integer :: A(N)
6 integer :: i, index,total
7
8 A = 1
9 total=0
10 index=1
11
12 !$omp parallel
13 !$omp single
14 do i = 1, N
15 !$omp task shared(A)
16 total = total + A(index) * 2
17 index=index+1
18 !$omp end task
19 end do
20 !$omp end single
21 !$omp taskwait
22 !$omp end parallel
23
24 print *, "Total = ", total, index
25 if(total/=10) error stop
26end program openmp_57Next Steps
For Week 7, I plan to:
- Implement the
teamsconstruct using theOMPRegionnode (Issue #7363). - Fix more bugs and implement other clauses if possible for
TASKS
I am grateful to my mentors, Ondrej Certik, Pranav Goswami, and Gaurav Dhingra, for their expert guidance during this debugging process. I also thank the LFortran community for their support and encouragement.