c语言 - 与 OpenMP 线程私有变量的初始化混淆



这些天我在学习OpenMP,我刚刚满足了"threadprivate"指令。下面由我自己编写的代码片段没有输出预期的结果:

// **** File: fun.h **** //
void seed(int x);
int drand();
// ********************* //
// **** File: fun.c **** //
extern int num;
int drand()
{
num = num + 1;
return num;
}
void seed(int num_initial)
{
num = num_initial;
}
// ************************ //
// **** File: main.c **** //
#include  "fun.h"
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int num = 0;
#pragma omp threadprivate(num)
int main()
{
int num_inital = 4;

seed(num_inital);
printf("At the beginning, num = %dn", num);  // should num be 4?
#pragma omp parallel for num_threads(2) schedule(static,1) copyin(num)
for (int ii = 0; ii < 4; ii++) {    
int my_rank = omp_get_thread_num();
//printf("Before processing, in thread %d num = %dn", my_rank,num);
int num_in_loop = drand();
printf("Thread %d is processing loop %d: num = %dn", my_rank,ii, num_in_loop);
}
system("pause");
return 0;
}
// ********************* //

下面列出我的问题:

  1. 为什么printf("At the beginning, num = %dn", num);的结果是num = 0而不是num = 4

  2. 对于并行for循环,多次执行会产生不同的结果,其中之一是:

Thread 1 is processing loop 1: num = 5
Thread 0 is processing loop 0: num = 6
Thread 1 is processing loop 3: num = 7
Thread 0 is processing loop 2: num = 8

似乎在for循环中num被初始化为4,这表示copyin子句中的num等于4。为什么printf("At the beginning, num = %dn", num)中的numcopyin中的不同?

  1. 在OpenMP网站上,它说

    在并行区域中,主线程对遇到并行区域的线程中变量副本的引用。

    根据这个解释,线程0(主线程(应该首先包含num = 4。因此,循环0的输出应该始终为:Thread 0 is processing loop 0: num = 5。为什么上面的结果不同?

我的工作环境是带有VS2015的win10操作系统。

我认为问题出在fun.c编译单元内。编译器无法确定extern int num;变量也是TLS变量。

我将在这个文件中包括指令#pragma omp threadprivate(num)

// **** File: fun.c **** //
extern int num;
#pragma omp threadprivate(num)
int drand()
{
num = num + 1;
return num;
}
void seed(int num_initial)
{
num = num_initial;
}
// ************************ //

在任何情况下,编译器都应该在链接阶段对此发出警告。

copyin子句用于OpenMP团队(例如计算加速器上的计算(。

事实上,OpenMP文档中写道:

这些子句支持将数据值从一个隐式任务或线程上的private或threadprivate变量复制到团队中其他隐式任务和线程上的相应变量。

因此,在您的情况下,您应该使用子句firstprivate

请注意,VS2015可能不支持您正在阅读的OpenMP文档的版本(5.0(。我建议您阅读与VS2015兼容的旧版本。编译程序的结果可能是未定义的。

最新更新