Skip to content

Commit

Permalink
[OpenMP][Tools] Add omp_all_memory support for Archer
Browse files Browse the repository at this point in the history
The semantic of depend(out:omp_all_memory) is quite similar to taskwait in
that it separates all tasks (with dependency) created before an
all_memory-task from all tasks (with dependency) created after an
all_memory-task.
Only a single of such tasks can execute at a time. Similar to taskwait, we
have a CV (AllMemory[1]) in the generating task to express the dependency
sink semantic of an all_memory-task. In addition, AllMemory[0] describes the
dependency source semantic of an all_memory-task. All tasks with dependency
create an HB-arc towards the sink and terminate an HB-arc from the source.

Since we expect that not many applications will use such dependency, the
support for handling the synchronization semantic is off by default and
can be turned on using ARCHER_OPTION="all_memory=1". The most costly part
is the precautionary posting of an HB-arc towards the sink, which represents
a potentially contentious write from all concurrently executing sibling tasks.
A warning is printed at runtime, when the option is off while such dependency
is observed. In most cases the lazy activation will still lead to false alerts.

Differential Revision: https://reviews.llvm.org/D111895
  • Loading branch information
jprotze committed Jul 7, 2023
1 parent d68aae3 commit 73d411d
Show file tree
Hide file tree
Showing 3 changed files with 411 additions and 2 deletions.
12 changes: 12 additions & 0 deletions openmp/tools/archer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ statement in main!)</td>
</tr>
</tbody>

<tbody>
<tr>
<td class="org-left">all&#95;memory</td>
<td class="org-right">0</td>
<td class="org-left">Turn on tracking and analysis of omp_all_memory
dependencies. Archer will activate the support automatically when
such dependency is seen during execution. At this time the analysis
already missed synchronization semantics, which will lead to false
reports in most cases.</td>
</tr>
</tbody>

<tbody>
<tr>
<td class="org-left">report&#95;data&#95;leak</td>
Expand Down
51 changes: 49 additions & 2 deletions openmp/tools/archer/ompt-tsan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ class ArcherFlags {
int enabled{1};
int report_data_leak{0};
int ignore_serial{0};
std::atomic<int> all_memory{0};

ArcherFlags(const char *env) {
if (env) {
std::vector<std::string> tokens;
std::string token;
std::string str(env);
std::istringstream iss(str);
int tmp_int;
while (std::getline(iss, token, ' '))
tokens.push_back(token);

Expand All @@ -89,6 +91,10 @@ class ArcherFlags {
continue;
if (sscanf(it->c_str(), "ignore_serial=%d", &ignore_serial))
continue;
if (sscanf(it->c_str(), "all_memory=%d", &tmp_int)) {
all_memory = tmp_int;
continue;
}
std::cerr << "Illegal values for ARCHER_OPTIONS variable: " << token
<< std::endl;
}
Expand Down Expand Up @@ -451,6 +457,9 @@ struct TaskData final : DataPoolEntry<TaskData> {
/// this task.
ompt_tsan_clockid Taskwait{0};

/// Child tasks use its address to model omp_all_memory dependencies
ompt_tsan_clockid AllMemory[2]{0};

/// Whether this task is currently executing a barrier.
bool InBarrier{false};

Expand Down Expand Up @@ -506,10 +515,16 @@ struct TaskData final : DataPoolEntry<TaskData> {
bool isInitial() { return TaskType & ompt_task_initial; }
bool isTarget() { return TaskType & ompt_task_target; }

void setAllMemoryDep() { AllMemory[0] = 1; }
bool hasAllMemoryDep() { return AllMemory[0]; }

void *GetTaskPtr() { return &Task; }

void *GetTaskwaitPtr() { return &Taskwait; }

void *GetLastAllMemoryPtr() { return AllMemory; }
void *GetNextAllMemoryPtr() { return AllMemory + 1; }

TaskData *Init(TaskData *parent, int taskType) {
TaskType = taskType;
Parent = parent;
Expand Down Expand Up @@ -855,13 +870,30 @@ static void freeTask(TaskData *task) {
}
}

// LastAllMemoryPtr marks the beginning of an all_memory epoch
// NextAllMemoryPtr marks the end of an all_memory epoch
// All tasks with depend begin execution after LastAllMemoryPtr
// and end before NextAllMemoryPtr
static void releaseDependencies(TaskData *task) {
if (archer_flags->all_memory) {
if (task->hasAllMemoryDep()) {
TsanHappensBefore(task->Parent->GetLastAllMemoryPtr());
TsanHappensBefore(task->Parent->GetNextAllMemoryPtr());
} else if (task->DependencyCount)
TsanHappensBefore(task->Parent->GetNextAllMemoryPtr());
}
for (unsigned i = 0; i < task->DependencyCount; i++) {
task->Dependencies[i].AnnotateEnd();
}
}

static void acquireDependencies(TaskData *task) {
if (archer_flags->all_memory) {
if (task->hasAllMemoryDep())
TsanHappensAfter(task->Parent->GetNextAllMemoryPtr());
else if (task->DependencyCount)
TsanHappensAfter(task->Parent->GetLastAllMemoryPtr());
}
for (unsigned i = 0; i < task->DependencyCount; i++) {
task->Dependencies[i].AnnotateBegin();
}
Expand Down Expand Up @@ -983,13 +1015,28 @@ static void ompt_tsan_dependences(ompt_data_t *task_data,
Data->Dependencies =
(TaskDependency *)malloc(sizeof(TaskDependency) * ndeps);
Data->DependencyCount = ndeps;
for (int i = 0; i < ndeps; i++) {
for (int i = 0, d = 0; i < ndeps; i++, d++) {
if (deps[i].dependence_type == ompt_dependence_type_out_all_memory ||
deps[i].dependence_type == ompt_dependence_type_inout_all_memory) {
Data->setAllMemoryDep();
Data->DependencyCount--;
if (!archer_flags->all_memory) {
printf("The application uses omp_all_memory, but Archer was\n"
"started to not consider omp_all_memory. This can lead\n"
"to false data race alerts.\n"
"Include all_memory=1 in ARCHER_OPTIONS to consider\n"
"omp_all_memory from the beginning.\n");
archer_flags->all_memory = 1;
}
d--;
continue;
}
auto ret = Data->Parent->DependencyMap->insert(
std::make_pair(deps[i].variable.ptr, nullptr));
if (ret.second) {
ret.first->second = DependencyData::New();
}
new ((void *)(Data->Dependencies + i))
new ((void *)(Data->Dependencies + d))
TaskDependency(ret.first->second, deps[i].dependence_type);
}

Expand Down
Loading

0 comments on commit 73d411d

Please sign in to comment.