我正在尝试使用OpenMP并行化C程序。
我想了解更多关于:
据我所知,不同之处在于 threadprivate 的全局范围以及跨并行区域的保留值。我在几个例子中发现,当一段代码包含一些必须私有化的全局/静态变量时,这些变量包含在 threadprivate 列表中,并且使用 COPYIN 即可。
但是,是否有任何规则阻止我们使用私有子句来处理全局/静态变量?也许任何实施细节?
我在OpenMP3.0规范中找不到任何解释。
答案 0 :(得分:20)
你必须记住的最重要的差异:
private
变量是区域的本地变量,大部分时间都会放在堆栈上。变量隐私的生命周期是数据范围子句定义的持续时间。每个线程(包括主线程)都会创建原始变量的私有副本(新变量不再与原始变量存储关联)。
另一方面,threadprivate
变量很可能放在堆或 thread local storage 中(可以被视为线程本地的全局内存)。 threadprivate
变量会跨区域持续存在(取决于某些限制)。主线程使用原始变量,所有其他线程都创建原始变量的私有副本(主变量仍然与原始变量存储关联)。
还有更棘手的差异:
定义为private
的变量在进入构造时未定义每个线程,并且在退出并行构造时未定义相应的共享变量; <{1}}指针的初始状态是未定义的。
但是,除非指定private
子句,否则应假定threadprivate
公共块中的数据在进入第一个并行区域时未定义。当公共块出现在copyin
指令中时,每个线程副本在首次使用之前初始化一次。
OpenMP Specifications(第2.14.2节)实际上给出了threadprivate
指令的非常好的描述(也更详细):
threadprivate
变量的每个副本以程序指定的方式初始化一次,但在第一次引用该副本之前在程序中未指定的位置初始化。根据静态变量在基本语言中的处理方式,但是在程序中未指定的位置,可以释放threadprivate
变量的所有副本的存储。线程引用另一个线程的
threadprivate
变量副本的程序不符合。如果执行线程切换到修改变量的另一个任务,则
threadprivate
变量的内容可以在任务调度点上更改。有关任务调度的更多详细信息,请参见第14页上的第1.3节和第113页上的第2.11节。在
threadprivate
区域中,主线程的引用将是遇到parallel
区域的线程中变量的副本。在顺序部件中,引用将是初始线程的变量副本。初始线程的
parallel
变量副本中的数据值保证在程序中对变量的任何两个连续引用之间保持不变。只有满足以下所有条件时,非初始线程的
threadprivate
变量中的数据值才会保证在两个连续的活动threadprivate
区域之间保持不变:
parallel
区域都没有嵌套在另一个显式parallel
区域内。用于执行两个
parallel
区域的线程数相同。用于执行两个
parallel
区域的线程相关性策略是相同的。在两个
parallel
区域的入口处,封闭任务区域中 dyn-var 内部控制变量的值为 false 。如果这些条件都成立,并且两个区域中都引用了
parallel
变量,则各自区域中具有相同线程编号的线程将引用该变量的相同副本。