Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7264527

Browse files
[OMPT][Offload][OpenMP] Fixes for OMPT data used by libomptarget (#156020)
These commits fix issues regarding storage of tool data within libomptarget. Both libomp and libomptarget have been modified to accommodate this. We differentiate between two cases depending on the type of the target region: - merged target regions (default, without `nowait` clause): behavior remains unchanged, tool data is stored in the thread local RegionInterface class within libomptarget. - deferred target regions (using `nowait` clause): tool data is moved to `ompt_task_info_t` struct within libomp, as `RegionInterface` is thread local and its data is lost whenever another task is scheduled on the thread, which happens with deferred target regions. In the new implementation, `RegionInterface` receives pointers to `ompt_task_info_t` within libomp which are handled transparently within libomptarget. Thus, the problem of tool data getting lost when a thread receives a new task is resolved: `target_data` and `target_task_data` remain set. Another issue was the value of `task_data` which is supposed to belong to the generating task of the region according to the OpenMP standard, but instead had been set to the `task_data` of the target task itself until now. Test cases have been added which check both of these fixes. --------- Co-authored-by: Joachim <[email protected]>
1 parent 2093d2e commit 7264527

11 files changed

Lines changed: 516 additions & 33 deletions

File tree

offload/include/OpenMP/OMPT/Interface.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,23 @@
2525

2626
#define OMPT_IF_BUILT(stmt) stmt
2727

28+
#define TargetTaskData \
29+
((OmptTaskInfoPtr == &OmptTaskInfo) ? nullptr \
30+
: (&(OmptTaskInfoPtr->task_data)))
31+
#define TargetData (OmptTaskInfoPtr->target_data)
32+
33+
/// Prefix of ompt_task_info_t struct from libomp
34+
typedef struct ompt_task_info_t {
35+
ompt_data_t task_data;
36+
ompt_data_t target_data;
37+
} ompt_task_info_t;
38+
2839
/// Callbacks for target regions require task_data representing the
2940
/// encountering task.
3041
/// Callbacks for target regions and target data ops require
3142
/// target_task_data representing the target task region.
3243
typedef ompt_data_t *(*ompt_get_task_data_t)();
33-
typedef ompt_data_t *(*ompt_get_target_task_data_t)();
44+
typedef ompt_task_info_t *(*ompt_get_task_info_target_t)();
3445

3546
namespace llvm {
3647
namespace omp {
@@ -40,7 +51,7 @@ namespace ompt {
4051
/// Function pointers that will be used to track task_data and
4152
/// target_task_data.
4253
static ompt_get_task_data_t ompt_get_task_data_fn;
43-
static ompt_get_target_task_data_t ompt_get_target_task_data_fn;
54+
static ompt_get_task_info_target_t ompt_get_task_info_target_fn;
4455

4556
/// Used to maintain execution state for this thread
4657
class Interface {
@@ -216,16 +227,16 @@ class Interface {
216227

217228
private:
218229
/// Target operations id
219-
ompt_id_t HostOpId = 0;
220-
221-
/// Target region data
222-
ompt_data_t TargetData = ompt_data_none;
230+
ompt_id_t HostOpId{0};
223231

224232
/// Task data representing the encountering task
225-
ompt_data_t *TaskData = nullptr;
233+
ompt_data_t *TaskData{nullptr};
234+
235+
/// TaskInfo contains target_data and task_data
236+
ompt_task_info_t OmptTaskInfo{ompt_data_none, ompt_data_none};
226237

227-
/// Target task data representing the target task region
228-
ompt_data_t *TargetTaskData = nullptr;
238+
/// Ptr to TaskInfo in OpenMP runtime in case of deferred target tasks
239+
ompt_task_info_t *OmptTaskInfoPtr{&OmptTaskInfo};
229240

230241
/// Used for marking begin of a data operation
231242
void beginTargetDataOperation();

offload/libomptarget/OpenMP/OMPT/Callback.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ bool llvm::omp::target::ompt::Initialized = false;
5151

5252
ompt_get_callback_t llvm::omp::target::ompt::lookupCallbackByCode = nullptr;
5353
ompt_function_lookup_t llvm::omp::target::ompt::lookupCallbackByName = nullptr;
54-
ompt_get_target_task_data_t ompt_get_target_task_data_fn = nullptr;
5554
ompt_get_task_data_t ompt_get_task_data_fn = nullptr;
55+
ompt_get_task_info_target_t ompt_get_task_info_target_fn = nullptr;
5656

5757
/// Unique correlation id
5858
static std::atomic<uint64_t> IdCounter(1);
@@ -424,18 +424,18 @@ void Interface::beginTargetRegion() {
424424
// Set up task state
425425
assert(ompt_get_task_data_fn && "Calling a null task data function");
426426
TaskData = ompt_get_task_data_fn();
427-
// Set up target task state
428-
assert(ompt_get_target_task_data_fn &&
429-
"Calling a null target task data function");
430-
TargetTaskData = ompt_get_target_task_data_fn();
431-
// Target state will be set later
432-
TargetData = ompt_data_none;
427+
// Set up target task and target state
428+
assert(ompt_get_task_info_target_fn &&
429+
"Calling a null target task info function");
430+
// In case of deferred target tasks, use pointer from libomp
431+
if (ompt_task_info_t *TempTaskInfoPtr = ompt_get_task_info_target_fn())
432+
OmptTaskInfoPtr = TempTaskInfoPtr;
433433
}
434434

435435
void Interface::endTargetRegion() {
436436
TaskData = 0;
437-
TargetTaskData = 0;
438-
TargetData = ompt_data_none;
437+
OmptTaskInfo = {ompt_data_none, ompt_data_none};
438+
OmptTaskInfoPtr = &OmptTaskInfo;
439439
}
440440

441441
/// Used to maintain the finalization functions that are received
@@ -474,7 +474,7 @@ int llvm::omp::target::ompt::initializeLibrary(ompt_function_lookup_t lookup,
474474

475475
bindOmptFunctionName(ompt_get_callback, lookupCallbackByCode);
476476
bindOmptFunctionName(ompt_get_task_data, ompt_get_task_data_fn);
477-
bindOmptFunctionName(ompt_get_target_task_data, ompt_get_target_task_data_fn);
477+
bindOmptFunctionName(ompt_get_task_info_target, ompt_get_task_info_target_fn);
478478
#undef bindOmptFunctionName
479479

480480
// Store pointer of 'ompt_libomp_target_fn_lookup' for use by libomptarget
@@ -483,8 +483,6 @@ int llvm::omp::target::ompt::initializeLibrary(ompt_function_lookup_t lookup,
483483
assert(lookupCallbackByCode && "lookupCallbackByCode should be non-null");
484484
assert(lookupCallbackByName && "lookupCallbackByName should be non-null");
485485
assert(ompt_get_task_data_fn && "ompt_get_task_data_fn should be non-null");
486-
assert(ompt_get_target_task_data_fn &&
487-
"ompt_get_target_task_data_fn should be non-null");
488486
assert(LibraryFinalizer == nullptr &&
489487
"LibraryFinalizer should not be initialized yet");
490488

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#define SKIP_CALLBACK_REGISTRATION 1
2+
3+
#include "../../../openmp/runtime/test/ompt/callback.h"
4+
#include "callbacks.h"
5+
#include <omp-tools.h>
6+
7+
// From openmp/runtime/test/ompt/callback.h
8+
#define register_ompt_callback_t(name, type) \
9+
do { \
10+
type f_##name = &on_##name; \
11+
if (ompt_set_callback(name, (ompt_callback_t)f_##name) == ompt_set_never) \
12+
printf("0: Could not register callback '" #name "'\n"); \
13+
} while (0)
14+
15+
#define register_ompt_callback(name) register_ompt_callback_t(name, name##_t)
16+
17+
// Init functions
18+
int ompt_initialize(ompt_function_lookup_t lookup, int initial_device_num,
19+
ompt_data_t *tool_data) {
20+
ompt_set_callback = (ompt_set_callback_t)lookup("ompt_set_callback");
21+
22+
if (!ompt_set_callback)
23+
return 0; // failed
24+
25+
// host runtime functions
26+
ompt_get_unique_id = (ompt_get_unique_id_t)lookup("ompt_get_unique_id");
27+
ompt_get_thread_data = (ompt_get_thread_data_t)lookup("ompt_get_thread_data");
28+
ompt_get_task_info = (ompt_get_task_info_t)lookup("ompt_get_task_info");
29+
30+
ompt_get_unique_id();
31+
32+
// host callbacks
33+
register_ompt_callback(ompt_callback_sync_region);
34+
register_ompt_callback_t(ompt_callback_sync_region_wait,
35+
ompt_callback_sync_region_t);
36+
register_ompt_callback_t(ompt_callback_reduction,
37+
ompt_callback_sync_region_t);
38+
register_ompt_callback(ompt_callback_implicit_task);
39+
register_ompt_callback(ompt_callback_parallel_begin);
40+
register_ompt_callback(ompt_callback_parallel_end);
41+
register_ompt_callback(ompt_callback_task_create);
42+
register_ompt_callback(ompt_callback_task_schedule);
43+
44+
// device callbacks
45+
register_ompt_callback(ompt_callback_device_initialize);
46+
register_ompt_callback(ompt_callback_device_finalize);
47+
register_ompt_callback(ompt_callback_device_load);
48+
register_ompt_callback(ompt_callback_target_data_op_emi);
49+
register_ompt_callback(ompt_callback_target_emi);
50+
register_ompt_callback(ompt_callback_target_submit_emi);
51+
52+
return 1; // success
53+
}
54+
55+
void ompt_finalize(ompt_data_t *tool_data) {}
56+
57+
#ifdef __cplusplus
58+
extern "C" {
59+
#endif
60+
ompt_start_tool_result_t *ompt_start_tool(unsigned int omp_version,
61+
const char *runtime_version) {
62+
static ompt_start_tool_result_t ompt_start_tool_result = {&ompt_initialize,
63+
&ompt_finalize, 0};
64+
return &ompt_start_tool_result;
65+
}
66+
#ifdef __cplusplus
67+
}
68+
#endif
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// clang-format off
2+
// RUN: env LIBOMP_NUM_HIDDEN_HELPER_THREADS=1 %libomptarget-compile-run-and-check-generic
3+
// REQUIRES: ompt
4+
// clang-format on
5+
6+
#include <inttypes.h>
7+
#include <omp-tools.h>
8+
#include <omp.h>
9+
#include <stdio.h>
10+
#include <string.h>
11+
12+
#include "register_with_host.h"
13+
14+
#define N 1000000
15+
#define M 1000
16+
17+
int main() {
18+
float *x = malloc(N * sizeof(float));
19+
float *y = malloc(N * sizeof(float));
20+
21+
for (int i = 0; i < N; i++) {
22+
x[i] = 1;
23+
y[i] = 1;
24+
}
25+
26+
#pragma omp target enter data map(to : x[0 : N]) map(alloc : y[0 : N])
27+
#pragma omp target teams distribute parallel for
28+
for (int i = 0; i < N; i++) {
29+
for (int j = 0; j < M; j++) {
30+
y[i] += 3 * x[i];
31+
}
32+
}
33+
34+
#pragma omp target teams distribute parallel for
35+
for (int i = 0; i < N; i++) {
36+
for (int j = 0; j < M; j++) {
37+
y[i] += 3 * x[i];
38+
}
39+
}
40+
41+
#pragma omp target exit data map(release : x[0 : N]) map(from : y[0 : N])
42+
43+
printf("%f, %f\n", x[0], y[0]);
44+
45+
free(x);
46+
free(y);
47+
return 0;
48+
}
49+
50+
// clang-format off
51+
/// CHECK: ompt_event_initial_task_begin
52+
/// CHECK-SAME: task_id=[[ENCOUNTERING_TASK:[0-f]+]]
53+
54+
/// CHECK: Callback Target EMI: kind=ompt_target_enter_data endpoint=ompt_scope_begin
55+
/// CHECK-SAME: task_data=0x{{[0-f]+}} (0x[[ENCOUNTERING_TASK]])
56+
/// CHECK-SAME: target_task_data=(nil) (0x0)
57+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA:[0-f]+]])
58+
59+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin
60+
/// CHECK-SAME: target_task_data=(nil) (0x0)
61+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
62+
63+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end
64+
/// CHECK-SAME: target_task_data=(nil) (0x0)
65+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
66+
67+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin
68+
/// CHECK-SAME: target_task_data=(nil) (0x0)
69+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
70+
71+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end
72+
/// CHECK-SAME: target_task_data=(nil) (0x0)
73+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
74+
75+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin
76+
/// CHECK-SAME: target_task_data=(nil) (0x0)
77+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
78+
79+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end
80+
/// CHECK-SAME: target_task_data=(nil) (0x0)
81+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
82+
83+
/// CHECK: Callback Target EMI: kind=ompt_target_enter_data endpoint=ompt_scope_end
84+
/// CHECK-SAME: task_data=0x{{[0-f]+}} (0x[[ENCOUNTERING_TASK]])
85+
/// CHECK-SAME: target_task_data=(nil) (0x0)
86+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
87+
88+
/// CHECK: Callback Target EMI: kind=ompt_target endpoint=ompt_scope_begin
89+
/// CHECK-SAME: task_data=0x{{[0-f]+}} (0x[[ENCOUNTERING_TASK]])
90+
/// CHECK-SAME: target_task_data=(nil) (0x0)
91+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA:[0-f]+]])
92+
93+
/// CHECK: Callback Submit EMI: endpoint=ompt_scope_begin
94+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
95+
96+
/// CHECK: Callback Submit EMI: endpoint=ompt_scope_end
97+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
98+
99+
/// CHECK: Callback Target EMI: kind=ompt_target endpoint=ompt_scope_end
100+
/// CHECK-SAME: task_data=0x{{[0-f]+}} (0x[[ENCOUNTERING_TASK]])
101+
/// CHECK-SAME: target_task_data=(nil) (0x0)
102+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
103+
104+
/// CHECK: Callback Target EMI: kind=ompt_target endpoint=ompt_scope_begin
105+
/// CHECK-SAME: task_data=0x{{[0-f]+}} (0x[[ENCOUNTERING_TASK]])
106+
/// CHECK-SAME: target_task_data=(nil) (0x0)
107+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA:[0-f]+]])
108+
109+
/// CHECK: Callback Submit EMI: endpoint=ompt_scope_begin
110+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
111+
112+
/// CHECK: Callback Submit EMI: endpoint=ompt_scope_end
113+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
114+
115+
/// CHECK: Callback Target EMI: kind=ompt_target endpoint=ompt_scope_end
116+
/// CHECK-SAME: task_data=0x{{[0-f]+}} (0x[[ENCOUNTERING_TASK]])
117+
/// CHECK-SAME: target_task_data=(nil) (0x0)
118+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
119+
120+
/// CHECK: Callback Target EMI: kind=ompt_target_exit_data endpoint=ompt_scope_begin
121+
/// CHECK-SAME: task_data=0x{{[0-f]+}} (0x[[ENCOUNTERING_TASK]])
122+
/// CHECK-SAME: target_task_data=(nil) (0x0)
123+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA:[0-f]+]])
124+
125+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin
126+
/// CHECK-SAME: target_task_data=(nil) (0x0)
127+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
128+
129+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end
130+
/// CHECK-SAME: target_task_data=(nil) (0x0)
131+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
132+
133+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin
134+
/// CHECK-SAME: target_task_data=(nil) (0x0)
135+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
136+
137+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end
138+
/// CHECK-SAME: target_task_data=(nil) (0x0)
139+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
140+
141+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin
142+
/// CHECK-SAME: target_task_data=(nil) (0x0)
143+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
144+
145+
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end
146+
/// CHECK-SAME: target_task_data=(nil) (0x0)
147+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])
148+
149+
/// CHECK: Callback Target EMI: kind=ompt_target_exit_data endpoint=ompt_scope_end
150+
/// CHECK-SAME: task_data=0x{{[0-f]+}} (0x[[ENCOUNTERING_TASK]])
151+
/// CHECK-SAME: target_task_data=(nil) (0x0)
152+
/// CHECK-SAME: target_data=0x{{[0-f]+}} (0x[[TARGET_DATA]])

0 commit comments

Comments
 (0)