ender46
ender46

Reputation: 3

OpenMP 4.5 task dependencies and execution order

I am trying to get OpenMP task dependencies to work, to no avail. Let's take this simplified example:

int main()
{
int x=0;

#pragma omp parallel
#pragma omp single
{
#pragma omp task depend(in:x)
  {
  #pragma omp critical
  cout << "Read the value " << x << "\n";
  }
#pragma omp task depend(out:x)
  {
  x = 3;
  #pragma omp critical
  cout << "Set the value to " << x << "\n";
  }
}
return 0;
}

As far as I understand (frome OpenMP specs), the depend(in:x) tasks should only be executed after all depend(out:x) tasks have been resolved, and so the expected output is

Set the value to 3
Read the value 3

However, the tasks are instead executed in semantic order, disregarding the depend clauses, and what I get is this:

Read the value 0
Set the value to 3

I am compiling using g++-7 (SUSE Linux) 7.3.1 20180323 [gcc-7-branch revision 258812] with the -fopenmp flag. This version of the compiler should have access to OpenMP 4.5.

Is this a misunderstanding of task dependencies on my side, or is there anything else at play here?

Upvotes: 0

Views: 1236

Answers (1)

Sergio Monteleone
Sergio Monteleone

Reputation: 2886

The concept of task dependencies can be misleading.

The best way to put it is to think about them as a way to indicate how different tasks access data and not as a way to control execution order.

The order of the tasks in the source code, together with the depend clause, describe one of the possibile 4 scenarios: read after write, write after read, write after write and read after read.

In your example, you are describing a write after read case: you are telling the compiler that the second task will overwrite the variable x, but the first task takes x as an input, as indicated by depend(in:x). Therefore, the software will execute the first task before the second to prevent overwriting the initial value.

If you have a look at Intel's documentation here there's a brief example which shows how tasks order (in the source code) still plays a role in the determination of the dependency graph (and therefore, on the execution order).

Another informative page on this matter is available here.

Upvotes: 3

Related Questions