我运行了 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);
}
该计划的输出是:
正确的输出应该是:
count1 = 100
count2 = 200
counter = 0/100/200?
它有什么问题?
答案 0 :(得分:2)
threadprivate
与private
的不同之处在于它不必为每个线程分配局部变量,变量只需对每个线程都是唯一的。其中一个线程(主)使用int counter = 0;
中定义的全局计数器。因此,此线程将此值更改为100,200或保持不变(0),具体取决于此单个线程开始执行的部分。
正如你所强调的那样,为什么程序为(count1,count2,counter)提供下一个结果:(100,300,300)和(100,300,0),这似乎很奇怪。
(100300300)
主线程执行两个部分。您可以通过单线程启动代码来检查它:OMP_NUM_THREADS=1 ./ex_omp
(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
。
如果count2 = 300
count
你应该注意到resize_window
不是私有的,那么它对于一个线程来说是私有的,而这个线程可以执行这两个部分。