[OpenMP][OMPT] `dispatch` callbacks are only dispatched once for static loops
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Given the following source code example:
```c
int main(void)
{
#pragma omp parallel for schedule(static, 1) num_threads(2)
for( int i = 0; i < 100; ++i )
{
}
}
```
An attached tool only receives a single `dispatch` callback per thread involved in the corresponding work sharing construct.
```console
$ ./a.out | grep -e callback_work -e callback_dispatch
[0][callback_work] work_type = loop_static | endpoint = begin | parallel_data->value = 666000001 (0x62e122d387e0) | task_data->value = 555000002 (0x62e122d397c0) | count = 100 | codeptr_ra = 0x62e0f4c8594a
[0][callback_dispatch] parallel_data->value = 666000001 (0x62e122d387e0) | task_data->value = 555000002 (0x62e122d397c0) | kind = ws_loop_chunk | instance->value = 140730807277400 | start = 0 | iterations = 1
[0][callback_work] work_type = loop_static | endpoint = end | parallel_data->value = 666000001 (0x62e122d387e0) | task_data->value = 555000002 (0x62e122d397c0) | count = 0 | codeptr_ra = 0x62e0f4c859bc
[1][callback_work] work_type = loop_static | endpoint = begin | parallel_data->value = 666000001 (0x62e122d387e0) | task_data->value = 555000003 (0x62e122d39900) | count = 100 | codeptr_ra = 0x62e0f4c8594a
[1][callback_dispatch] parallel_data->value = 666000001 (0x62e122d387e0) | task_data->value = 555000003 (0x62e122d39900) | kind = ws_loop_chunk | instance->value = 136196248296664 | start = 1 | iterations = 1
[1][callback_work] work_type = loop_static | endpoint = end | parallel_data->value = 666000001 (0x62e122d387e0) | task_data->value = 555000003 (0x62e122d39900) | count = 0 | codeptr_ra = 0x62e0f4c859bc
```
The `iterations` value matches the chunk size, but doesn't tell how many iterations might be executed in total.
Similar to #207746, the issue can be found in the code generated for static loops. For the outlined function, the following code is generated:
```llvm
; Function Attrs: noinline norecurse nounwind optnone uwtable
define internal void @main.omp_outlined(ptr noalias noundef %0, ptr noalias noundef %1) #1 {
[...]
call void @__kmpc_for_static_init_4(ptr @1, i32 %13, i32 33, ptr %10, ptr %7, ptr %8, ptr %9, i32 1, i32 1)
br label %14
[...]
47: ; preds = %20
call void @__kmpc_for_static_fini(ptr @1, i32 %13)
ret void
```
In total, two runtime calls are made. This gives the runtime two options to dispatch a `dispatch` callback.
For dynamic for example, we get another call:
```llvm
; Function Attrs: noinline norecurse nounwind optnone uwtable
define internal void @main.omp_outlined(ptr noalias noundef %0, ptr noalias noundef %1) #1 {
[...]
call void @__kmpc_dispatch_init_4(ptr @1, i32 %13, i32 1073741859, i32 0, i32 99, i32 1, i32 1)
br label %14
14: ; preds = %32, %2
%15 = call i32 @__kmpc_dispatch_next_4(ptr @1, i32 %13, ptr %10, ptr %7, ptr %8, ptr %9)
%16 = icmp ne i32 %15, 0
br i1 %16, label %17, label %33
[...]
33: ; preds = %14
call void @__kmpc_dispatch_deinit(ptr @1, i32 %13)
ret void
```
Hence, the runtime is able to dispatch a callback for each chunk. For static loops, a fix likely requires work in both the code generation for Clang & Flang, and the OpenMP runtime.
Contributor guide
Research direction
Start with the generated static-loop LLVM IR and compare its runtime calls with the dynamic-loop example. Then inspect the Clang and Flang lowering paths and the OpenMP runtime's static-loop OMPT dispatch handling. Re-run the provided two-thread source with an attached tool and verify that callbacks report every static-loop chunk.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100