在OpenMP中使用threadprivate时出错

时间:2018-06-14 13:28:46

标签: c openmp

我运行了 OpenMP 程序的示例来测试threadprivate的功能,但结果是意外且未确定的。 (该程序在VMware中的ubuntu 14.04上运行。)

源代码如下所示:

int counter = 0;
#pragma omp threadprivate (counter)
int inc_counter()
{
  counter++;
  return counter;
}

void main()
{
  #pragma omp parallel sections copyin(counter)
  {
    #pragma omp section
    {
      int count1;
      for(int iter = 0; iter < 100; ++iter)
        count1 = inc_counter();
      printf("count1 = %1d\n", count1);
    }
    #pragma omp section
    {
      int count2;
      for(int iter=0; iter<200; iter++)
        count2 = inc_counter();
      printf("count2 = %d\n", count2);
    }
  }
  printf("counter = %d\n", counter);
}
  

该计划的输出是:

enter image description here

正确的输出应该是:

count1 = 100
count2 = 200
counter = 0/100/200?

它有什么问题?

1 个答案:

答案 0 :(得分:2)

threadprivateprivate的不同之处在于它不必为每个线程分配局部变量,变量只需对每个线程都是唯一的。其中一个线程(主)使用int counter = 0;中定义的全局计数器。因此,此线程将此值更改为100,200或保持不变(0),具体取决于此单个线程开始执行的部分。

正如你所强调的那样,为什么程序为(count1,count2,counter)提供下一个结果:(100,300,300)和(100,300,0),这似乎很奇怪。

  1. (100300300)

    主线程执行两个部分。您可以通过单线程启动代码来检查它:OMP_NUM_THREADS=1 ./ex_omp

  2. (100,300,0)

    当master处于空闲状态时,某些线程会执行这两个部分。您可以通过介绍部分(与您的两个一起)来检查它:

    #pragma omp section
    {   
      sleep(1); // #include <unistd.h>
      printf("hope it is 0 (master) -> %d\n", omp_get_thread_num());
    }
    

    如果您有2个线程并且master开始执行此部分,那么另一个具有高概率的线程会执行您的另外两个部分,您将获得(100,300,0)预期。例如,以OMP_NUM_THREADS=2 ./ex_omp

  3. 启动

    如果count2 = 300 count你应该注意到resize_window不是私有的,那么它对于一个线程来说是私有的,而这个线程可以执行这两个部分。