OpenMP 中的 first private 和 last private 与 private 条款有什么不同?

我看了官方的定义,但我还是很困惑。

firstprivate: 指定每个线程应该有自己的变量实例,并且应该用变量的值初始化变量,因为它存在于并行结构之前。

对我来说,这听起来很私人。我一直在寻找例子,但我似乎不明白它是如何特殊或如何使用它。

lastprivate: 指定将封闭上下文的变量版本设置为相当于执行最终迭代(for-loop 结构)或最后部分(# 杂注部分)的线程的私有版本。

因为下面的例子,我觉得我对这个问题有了更好的理解:

#pragma omp parallel
{
#pragma omp for lastprivate(i)
for (i=0; i<n-1; i++)
a[i] = b[i] + b[i+1];
}
a[i]=b[i];

因此,在本例中,我理解 lastprivate允许将 i作为最后一个值在循环外返回。

我今天才开始学 OpenMP。

69915 次浏览

private variables are not initialised, i.e. they start with random values like any other local automatic variable (and they are often implemented using automatic variables on the stack of each thread). Take this simple program as an example:

#include <stdio.h>
#include <omp.h>


int main (void)
{
int i = 10;


#pragma omp parallel private(i)
{
printf("thread %d: i = %d\n", omp_get_thread_num(), i);
i = 1000 + omp_get_thread_num();
}


printf("i = %d\n", i);


return 0;
}

With four threads it outputs something like:

thread 0: i = 0
thread 3: i = 32717
thread 1: i = 32717
thread 2: i = 1
i = 10


(another run of the same program)


thread 2: i = 1
thread 1: i = 1
thread 0: i = 0
thread 3: i = 32657
i = 10

This clearly demonstrates that the value of i is random (not initialised) inside the parallel region and that any modifications to it are not visible after the parallel region (i.e. the variable keeps its value from before entering the region).

If i is made firstprivate, then it is initialised with the value that it has before the parallel region:

thread 2: i = 10
thread 0: i = 10
thread 3: i = 10
thread 1: i = 10
i = 10

Still modifications to the value of i inside the parallel region are not visible after it.

You already know about lastprivate (and it is not applicable to the simple demonstration program as it lacks worksharing constructs).

So yes, firstprivate and lastprivate are just special cases of private. The first one results in bringing in values from the outside context into the parallel region while the second one transfers values from the parallel region to the outside context. The rationale behind these data-sharing classes is that inside the parallel region all private variables shadow the ones from the outside context, i.e. it is not possible to use an assignment operation to modify the outside value of i from inside the parallel region.

You cannot use local variable i before initialization, the program will give an error since C++ 14 Standard.