Skip to content

Commit 59a994e

Browse files
vladaindjicjprotze
authored andcommitted
[OpenMP][OMPT] thread_num determination for programs with explicit tasks
__ompt_get_task_info_internal is now able to determine the right value of the “thread_num” argument during the execution of an explicit task. During the execution of a while loop that iterates over the ancestor tasks hierarchy, the “prev_team” variable was always set to “team” variable at the beginning of each loop iteration. Assume that the program contains a parallel region which encloses an explicit task executed by the worker thread of the region. Also assume that the tool inquires the “thread_num” of a worker thread for the implicit task that corresponds to the region (task at “ancestor_level == 1”) and expects to receive the value of “thread_num > 0”. After the loop finishes, both “team” and “prev_team” variables are equal and point to the team information of the parallel region. The “thread_num” is set to “prev_team->t.t_master_tid”, that is equal to “team->t.t_master_tid”. In this case, “team->t.t_master_tid” is 0, since the master thread of the region is the initial master thread of the program. This leads to a contradiction. To prevent this, “prev_team” variable is set to “team” variable only at the time when the loop that has already encountered the implicit task (“taskdata” variable contains the information about an implicit task) continues iterating over the implicit task’s ancestors, if any. After the mentioned loop finishes, the “prev_team” variable might be equal to NULL. This means that the task at requested “ancestor_level” belongs to the innermost parallel region, so the “thread_num” will be determined by calling the “__kmp_get_tid”. To prove that this patch works, the test case “explicit_task_thread_num.c” is provided. It contains the example of the program explained earlier in the summary. Differential Revision: https://reviews.llvm.org/D110473
1 parent c93fb14 commit 59a994e

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

openmp/runtime/src/ompt-specific.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,6 @@ int __ompt_get_task_info_internal(int ancestor_level, int *type,
369369

370370
while (ancestor_level > 0) {
371371
// needed for thread_num
372-
prev_team = team;
373372
prev_lwt = lwt;
374373
// next lightweight team (if any)
375374
if (lwt)
@@ -389,6 +388,7 @@ int __ompt_get_task_info_internal(int ancestor_level, int *type,
389388
taskdata = taskdata->td_parent;
390389
if (team == NULL)
391390
return 0;
391+
prev_team = team;
392392
team = team->t.t_parent;
393393
if (taskdata) {
394394
next_lwt = LWT_FROM_TEAM(taskdata->td_team);
@@ -432,7 +432,16 @@ int __ompt_get_task_info_internal(int ancestor_level, int *type,
432432
*thread_num = __kmp_get_tid();
433433
else if (prev_lwt)
434434
*thread_num = 0;
435-
else
435+
else if (!prev_team) {
436+
// The innermost parallel region contains at least one explicit task.
437+
// The task at level > 0 is either an implicit task that
438+
// corresponds to the mentioned region or one of the explicit tasks
439+
// nested inside the same region. Note that the task isn't the
440+
// innermost explicit tasks (because of condition level > 0).
441+
// Since the task at this level still belongs to the innermost parallel
442+
// region, thread_num is determined the same way as for level==0.
443+
*thread_num = __kmp_get_tid();
444+
} else
436445
*thread_num = prev_team->t.t_master_tid;
437446
// *thread_num = team->t.t_master_tid;
438447
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// RUN: %libomp-compile-and-run | FileCheck %s
2+
// REQUIRES: ompt
3+
4+
#include "callback.h"
5+
#include <omp.h>
6+
7+
8+
__attribute__ ((noinline)) // workaround for bug in icc
9+
void print_task_info_at(int ancestor_level, int id)
10+
{
11+
#pragma omp critical
12+
{
13+
int task_type;
14+
char buffer[2048];
15+
ompt_data_t *parallel_data;
16+
ompt_data_t *task_data;
17+
int thread_num;
18+
ompt_get_task_info(ancestor_level, &task_type, &task_data, NULL,
19+
&parallel_data, &thread_num);
20+
format_task_type(task_type, buffer);
21+
printf("%" PRIu64 ": ancestor_level=%d id=%d task_type=%s=%d "
22+
"parallel_id=%" PRIu64 " task_id=%" PRIu64
23+
" thread_num=%d\n",
24+
ompt_get_thread_data()->value, ancestor_level, id, buffer,
25+
task_type, parallel_data->value, task_data->value, thread_num);
26+
}
27+
};
28+
29+
int main()
30+
{
31+
32+
#pragma omp parallel num_threads(2)
33+
{
34+
35+
if (omp_get_thread_num() == 1) {
36+
// To assert that task is executed by the worker thread,
37+
// if(0) is used in order to ensure that the task is immediately
38+
// executed after its creation.
39+
#pragma omp task if(0)
40+
{
41+
// thread_num should be equal to 1 for both explicit and implicit task
42+
print_task_info_at(0, 1);
43+
print_task_info_at(1, 0);
44+
};
45+
}
46+
}
47+
48+
// Check if libomp supports the callbacks for this test.
49+
// CHECK-NOT: {{^}}0: Could not register callback 'ompt_event_parallel_begin'
50+
// CHECK-NOT: {{^}}0: Could not register callback 'ompt_callback_task_create'
51+
// CHECK-NOT: {{^}}0: Could not register callback 'ompt_callback_implicit_task'
52+
53+
// CHECK: {{^}}0: NULL_POINTER=[[NULL:.*$]]
54+
// CHECK: {{^}}[[MASTER_ID:[0-9]+]]: ompt_event_initial_task_begin
55+
56+
// parallel region used only to determine worker thread id
57+
// CHECK: {{^}}[[MASTER_ID]]: ompt_event_parallel_begin
58+
// CHECK-DAG: {{^}}[[MASTER_ID]]: ompt_event_implicit_task_begin
59+
// CHECK-DAG: {{^}}[[WORKER_ID:[0-9]+]]: ompt_event_implicit_task_begin
60+
61+
// thread_num must be equal to 1 for both explicit and the implicit tasks
62+
// CHECK: {{^}}[[WORKER_ID]]: ancestor_level=0 id=1 task_type=ompt_task_explicit
63+
// CHECK-SAME: thread_num=1
64+
// CHECK: {{^}}[[WORKER_ID]]: ancestor_level=1 id=0 task_type=ompt_task_implicit
65+
// CHECK-SAME: thread_num=1
66+
67+
return 0;
68+
}

0 commit comments

Comments
 (0)