我正在尝试运行以下代码以了解OpenMP lastprivate构造的功能。根据lastprivate的定义,如果我声明一个变量lastprivate,则它对每个线程都是私有的,并且按顺序执行并行循环最后一次迭代的线程的值将复制到该区域之外的变量中。
这是代码:

int main(void)
{
    omp_set_num_threads(5);
    int i;
    int k =3;
    #pragma omp parallel private(i)
    {
        #pragma omp for lastprivate(k)
        for(i=0; i< 5; i++ )
        {
            int iam = omp_get_thread_num();
            k = iam;
            printf("k=%d, iam=%d\t",k, iam);
        }
    }

    printf("\n k = %d", k);
}


它产生如下输出:

k=0, iam=0  k=4, iam=4  k=3, iam=3  k=2, iam=2  k=1, iam=1
k = 4


当我们有一组线程在“ for”中工作时,我们不能真正保证哪个线程最后执行。因此,因此,最后一个线程的值应反映在全局“ k”中。但是,无论我运行代码多少次,全局'k'的值(即并行段结束后)仍为4。

同样从打印的值中,我们可以看到线程1最后执行。即使我们假设打印不可靠以获取确切的线程运行顺序,也似乎显然线程4总是最后运行,从而将其值反映为“ k”似乎很远。

我将感谢您对这个问题的帮助。谢谢。

最佳答案

为了确保哪个线程最后执行,您应该打印迭代索引的值(而不是复制线程ID):

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

int main() {
  int kk;
#pragma omp parallel
  {
#pragma omp for schedule(runtime) lastprivate(kk)
    for(int ii=0; ii < 1000; ii++ ) {
      kk = omp_get_thread_num();
      printf("ii = %d, kk = %d\n",ii,kk);
    }
  }
  printf("kk = %d\n", kk);
  return 0;
}


如果运行此程序,您会注意到执行迭代999的线程会设置kk的值。

关于这句话(重点是我的):


  当我们有一组线程在“ for”中工作时,我们不能真正保证哪个线程最后执行。


您所说的通常是正确的,但有一个例外(OpenMP 3.1标准的2.5节):


  具有相同时间表和迭代次数的不同循环区域,
  即使它们出现在同一平行区域,也可以分布
  线程之间的迭代方式有所不同。唯一的例外是
  静态时间表...


现在,由于您未指定任何时间表,因此遵循以下规则:


  如果循环指令没有调度子句,则当前
  def-sched-var ICV的值确定计划


如果def-sched-var确定了schedule(static)(根据我的经验,是很多次),那么程序的最终打印将始终为k = 4

关于c - 为什么OpenMP lastprivate产生错误的结果?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17302517/

10-11 18:26