llvm / llvm/llvm-project

[OpenMP][OMPT] `dispatch` callbacks are only dispatched once for static loops

Open
#212,784 1 comment 0 reactions 0 assignees View on GitHub
openmp
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.