假设我们有一个变量
var=100
。子句 private(var)
创建 n 个附加 变量,为每个 n 线程分配一个变量:
Before parallelism, var's value and address are 100, 0x7ffd683992bc
private parallel region:
var's value and address in thread 3 are 3, 0x7feb115ffde8
var's value and address in thread 0 are 0, 0x7ffd68399258
var's value and address in thread 1 are 1, 0x7feb129ffde8
var's value and address in thread 2 are 2, 0x7feb11fffde8
After private parallelism, var's value and address are 100, 0x7ffd683992bc
这完全按照预期工作。然而,创建一个
threadprivate
区域,我们注意到:
Before parallelism, var's value and address are 100 and 0x7f685615c7bc
threadprivate parallel region:
var's value and address in thread 0 are 0 and 0x7f685615c7bc
var's value and address in thread 3 are 6 and 0x7f6854c006bc
var's value and address in thread 1 are 2 and 0x7f68560006bc
var's value and address in thread 2 are 4 and 0x7f68556006bc
After first tp parallelism, var's value and address are 0 and 0x7f685615c7bc
如您所见,
thread 0
的副本与原始变量共享相同的地址,并且此处的更改也反映在并行区域之外。
所有
private()
、firstprivate()
和 lastprivate()
都会产生 n 个额外的 变量,而 threadprivate()
只会再产生 n-1 个。这种行为的原因是什么?为什么要以这种方式工作?
threadprivate
用于静态或全局变量,为每个线程提供一个具有全局范围的副本(因此该变量在线程的生命周期内继续存在),而 {first|last|}private
声明变量应在每个线程中本地分配在进入并行区域时,然后在退出并行区域时销毁。
OpenMP 指定并行区域内的线程 0 是执行
parallel
指令的线程(OpenMP 标准 第 9 段:“当任何线程遇到并行构造时,该线程会创建一个由自身和零个或多个附加线程组成的团队”并成为新团队的主线程。”),因此它显然会继续为该预先存在的线程使用现有的、已分配的 threadprivate
变量。
因此,您所看到的行为正是您所期望的。
threadprivate
变量在线程的整个生命周期中都存在,并且不会为新并行区域内预先存在的线程零创建新实例。