简体   繁体   中英

How to use omp flush(how to explain the notes in openmp api about flush model)

This is a program from openmp API. How to explain the notes "Values of flag and data are undefined" and "Values data will be 42, value of flag still undefined"? In my opinion, when the program have run to the "line 23", the value data should be 42 and the value flag should be 1.

//Example mem_model.2c, from Chapter 2 (The OpenMP Memory Model)
int main() {
   int data, flag = 0;
   #pragma omp parallel num_threads(2)
   {
      if (omp_get_thread_num()==0) {
         /* Write to the data buffer that will be read by thread */
         data = 42;
         /* Flush data to thread 1 and strictly order the write to data
            relative to the write to the flag */
         #pragma omp flush(flag, data)
         /* Set flag to release thread 1 */
         flag = 1;
         /* Flush flag to ensure that thread 1 sees S-21 the change */
         #pragma omp flush(flag)
      }
      else if (omp_get_thread_num()==1) {
         /* Loop until we see the update to the flag */
         #pragma omp flush(flag, data)
         while (flag < 1) {
            #pragma omp flush(flag, data)
         }
         // **line 23**
         /* **Values of flag and data are undefined** */
         printf("flag=%d data=%d\n", flag, data);
         #pragma omp flush(flag, data)
         /* **Values data will be 42, value of flag still undefined** */
         printf("flag=%d data=%d\n", flag, data);
      }
   }
   return 0;
}

This example contains a data race due to the conflicting concurrent, non-atomic accesses to flag . According to the OpenMP specification, if a data race occurs then "the result of the program is unspecified".

The latest versions of the Examples document can be found at https://www.openmp.org/specifications/ . The example was corrected in the 5.0.1 version of the Examples document, to this:

#include <omp.h>
#include <stdio.h>
int main()
{
    int data;
    int flag=0;
    #pragma omp parallel num_threads(2)
    {
      if (omp_get_thread_num()==0)
      {
      /* Write to the data buffer that will be
       * read by thread */
          data = 42;
      /* Flush data to thread 1 and strictly order
       * the write to data relative to the write to the flag */
          #pragma omp flush(flag, data)
      /* Set flag to release thread 1 */
          #pragma omp atomic write
          flag = 1;
      }
      else if(omp_get_thread_num()==1)
      {
      /* Loop until we see the update to the flag */
          #pragma omp flush(flag, data)
          int flag_val = 0;
          while (flag_val < 1)
          {
             #pragma omp atomic read
             flag_val = flag;
          }
      /* Value of flag is 1; value of data is undefined */
          printf("flag=%d data=%d\n", flag, data);
          #pragma omp flush(flag, data)
      /* Value of flag is 1; value of data is 42 */
          printf("flag=%d data=%d\n", flag, data);
      }
    }
    return 0;
}

The use of atomic constructs on the flag variable will guarantee that flag has the value 1 upon exit from the while loop in the else block. This is because that atomic construct has an implicit flush on the variable that is atomically accessed. The subsequent flush directive will then ensure that the value observed for data is the value written by thread 0. Without that directive, the memory model permits an old value for data to be observed (eg, due to reordering of load instructions by the compiler or the hardware).

This is my understanding of the workflow:

Thread 1 will wait till flag is 1.

Thread 0 will write 42 to data and flush and 1 to flag and flush.

When the 1 is written to flag by thread 0, it could be read by thread 1 and break the loop (or not till the flush). This results in the undefined behavior in line 23. After that, the flush will ensure the correct value is read from the memory and written correctly.

However, when I tested again various versions of GCC and Intel compiler, it always output 1,42 for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM