简体   繁体   English

omp flush的使用方法(openmp api中关于flush模型的注释如何解释)

[英]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"?这是来自 openmp API 的程序。如何解释注释“标志和数据的值未定义”和“值数据将为 42,标志的值仍未定义”? 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.在我看来,当程序运行到“第 23 行”时,值数据应该是 42,值标志应该是 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 .由于对flag的并发非原子访问冲突,此示例包含数据竞争。 According to the OpenMP specification, if a data race occurs then "the result of the program is unspecified".根据 OpenMP 规范,如果发生数据竞争,则“程序的结果是未指定的”。

The latest versions of the Examples document can be found at https://www.openmp.org/specifications/ .可以在https://www.openmp.org/specifications/找到示例文档的最新版本。 The example was corrected in the 5.0.1 version of the Examples document, to this:该示例在示例文档的 5.0.1 版本中已更正为:

#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.flag变量上使用atomic构造将保证flag在退出else块中的while循环时具有值 1。 This is because that atomic construct has an implicit flush on the variable that is atomically accessed.这是因为该atomic构造对原子访问的变量具有隐式刷新。 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).随后的flush指令将确保观察到的data值是线程 0 写入的值。如果没有该指令,memory model 允许观察data的旧值(例如,由于编译器对加载指令的重新排序或硬件)。

This is my understanding of the workflow:这是我对工作流程的理解:

Thread 1 will wait till flag is 1.线程 1 将等待标志为 1。

Thread 0 will write 42 to data and flush and 1 to flag and flush.线程 0 会将 42 写入数据并刷新,将 1 写入标志并刷新。

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).当 1 被线程 0 写入标志时,它可以被线程 1 读取并中断循环(或者直到刷新)。 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.这会导致第 23 行出现未定义的行为。之后,刷新将确保从 memory 中读取并正确写入正确的值。

However, when I tested again various versions of GCC and Intel compiler, it always output 1,42 for me.然而,当我再次测试各种版本的 GCC 和 Intel 编译器时,它总是 output 1,42 对我来说。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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