openmp parallel for - 它如何处理以前的私有索引?

openmp parallel for - How does it handle previously private index?

我有一个包含 2 个并行 for 循环的并行块:

    int i, j;
    #pragma omp parallel
    {
      #pragma omp for
      for(i=0; i < foo; i++)
        work();


      #pragma omp for private(j)
      for(i=0; i < foo; i++)
        for(j=0, j < foo; j++)
          work();
    }

如果我像这样将其设为私有:

int i, j;
    #pragma omp parallel private(i)
    {
      #pragma omp for
      for(i=0; i < foo; i++)
        work();


      #pragma omp for private(j)
      for(i=0; i < foo; i++)
        for(j=0, j < foo; j++)
          work();
    }

那么我有 NUM_THREADS 份 i 份。 openMP 是否仍然能够基于 i 并行安排我的线程 for 循环以及如何?如果我不以这种方式将其设为私有(参见第一个代码示例),那么在两个 for 循环之间我可以期望 i 有什么行为?

它不是 duplicate,因为我知道您通常可以让 parralel 循环隐式创建 i 的私有版本,但我更关心的是它是否能像预期的那样使用之前私有的变量甚至在暂时私有的情况下甚至在之前工作过。

第二个 for 循环将无法编译,除非您将代码更改为

#pragma omp parallel
{
  #pragma omp for
  for(i=0; i < foo; i++)
    work();

  #pragma omp for private(j)
  for(i=0; i < foo; i++)
    for(j=0, j < foo; j++)
      work();
}

int i, j;
#pragma omp parallel private(i)
{
  #pragma omp for
  for(i=0; i < foo; i++)
    do();

  #pragma omp for private(j)
  for(i=0; i < foo; i++)
    for(j=0, j < foo; j++)
      work();
}

现在很清楚私有 i 的作用域是什么了。


修改后,所有4个for循环都将按预期工作。

Will openMP still be able to schedule my threads based on i in parallel for loops and how?

是的,在每个 #pragma omp for,私有 is 将被正确初始化并在并行中使用。

If I don't make it private that way (see first code example) then what behavior can I expect from i between the two for-loops?

#pragma omp for 定义的并行索引将始终是私有的,即使您将其声明为共享索引也是如此。所以您的第一个代码示例仍然有效。

其实根据这个答案声明i是否为私有并不重要

回答你的问题

what behaviour can I expect from i between the two for-loops?

在您的第一个示例中,i 仅在工作共享区域(在 for 循环中)是私有的。在两个工作共享区域之间,它仍然是共享的。在第二个示例中,自从您为并行区域声明 i private 以来,它在任何地方都是私有的。

这很容易显示。

i = 1;
#pragma omp parallel
{
    #pragma omp for
    for(i=0; i<10; i++);
    i = 10;
}
printf("%d\n", i);

这会打印 10 因为 i 是共享的,除了工作共享区域,每个线程都将 10 写入共享的 i.

然而,

i = 1;
#pragma omp parallel private(i)
{
    #pragma omp for
    for(i=0; i<10; i++);
    i = 10;
}
printf("%d\n", i);

打印1,因为i在整个并行区域是私有的,不会修改并行区域外的i

在您当前的代码中,因为您只在工作共享区域中使用 i 那么它没有任何区别,但是如果在循环之间的工作共享区域中不使用 i 它可能会有所不同.这可能会导致一个微妙的错误。由于您仅在工作共享区域中使用 i,因此我建议使用 for(int i=0; ... 在工作共享区域中声明 i 或将其声明为对整个区域私有。 j.

也是如此