Data Communication, Child Task

Occurs when a task writes a value that a different (child) task reads. A child task is a task nested inside another task.

Problem type: Data communication

ID

Code Location

Description

1

Allocation site

If present, represents the location and associated call stack when the memory block was allocated.

2

Parallel site

Represents the location and associated call stack of the parallel site containing the Data Communication problem.

3

Write

Represents the instruction and associated call stack where the memory was written.

4

Read

Represents the instruction and associated call stack where the memory was read in a different task execution.

Example

void problem()
{
    int* pointer = new int;               // Allocation site
    ANNOTATE_SITE_BEGIN(datacomm_site1);  // Begin parallel site
        ANNOTATE_TASK_BEGIN(task1);
            *pointer = 999;               // Write
        ANNOTATE_TASK_END();
        assert(*pointer == 999);          // Read
    ANNOTATE_SITE_END();
}

In this example, one task writes a heap-allocated int, then an ancestor task reads it.

void data_communication()
{
   ANNOTATE_SITE_BEGIN(data_communication_site);  // Parallel site
   {
     for (int i=0; i<N; i++) {       
       ANNOTATE_TASK_BEGIN(data_communication_task1);
       {
           communication++; /* write in child */  // Write
       }
       ANNOTATE_TASK_END();
       printf(“%d\n”, communication);  /* read in parent */  // Read
   }
   ANNOTATE_SITE_END();
}

In this example, the incremented variable is read after each task. This creates a serial dependence.

Possible Correction Strategies

If you can preserve the application's integrity, consider moving the reads by the parent task into the child task. In the example above, this would result in non-deterministic output. If moving the read is not possible, you may need to use a different strategy, such as pipelining the loop.

For more complete information about compiler optimizations, see our Optimization Notice.