87

我看过官方定义,但我仍然很困惑。

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

对我来说,这听起来很像私人的。我找了一些例子,但我似乎不明白它有什么特别之处或如何使用它。

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

由于以下示例,我觉得我对这一点的理解更好:

#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。

4

3 回答 3

179

private变量没有初始化,即它们像任何其他本地自动变量一样以随机值开始(并且它们通常使用每个线程堆栈上的自动变量来实现)。以这个简单的程序为例:

#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;
}

使用四个线程,它输出如下内容:

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

这清楚地表明 的值i在并行区域内是随机的(未初始化),并且在并行区域之后对其进行的任何修改都不可见(即变量在进入该区域之前保持其值)。

如果i是 made firstprivate,则使用它在并行区域之前的值进行初始化:

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

i在它之后仍然看不到并行区域内的值的修改。

您已经知道lastprivate(它不适用于简单的演示程序,因为它缺少工作共享结构)。

所以是的,firstprivate而且lastprivate只是private. 第一个导致将来自外部上下文的值引入并行区域,而第二个将值从并行区域传输到外部上下文。这些数据共享类背后的基本原理是,在并行区域内,所有私有变量都会遮蔽外部上下文中的私有变量,即不可能使用赋值操作来修改i并行区域内部的外部值。

于 2013-03-09T10:13:22.197 回答
8

firstprivate并且lastprivate只是 的特例private

第一个导致将来自外部上下文的值引入并行区域,而第二个导致将值从并行区域传输到外部上下文。

于 2017-01-20T10:10:27.233 回答
0

在初始化之前不能使用局部变量i,程序会报错,因为 C++ 14 标准。

于 2021-12-07T12:27:32.247 回答