对于

时间:2018-11-13 08:46:32

标签: c++ openmp

看一下文档here,以下结构得到了很好的定义:

#pragma omp parallel          //Line 1
{
#pragma omp for nowait        //Line 3
  for (i=0; i<N; i++)
    a[i] = // some expression
#pragma omp for               //Line 6
  for (i=0; i<N; i++)
    b[i] = ...... a[i] ......
}

  

在这里,nowait子句意味着线程可以在第二个循环中启动,而其他线程仍在第一个循环中工作。由于两个循环在此处使用相同的计划,因此使用a [i]的迭代确实可以依靠它来计算该值。

我很难理解为什么会这样。假设Line 3是:

#pragma omp for

然后,由于在Line 6之前有一个隐式屏障,因此下一个for循环将在a的所有索引处都具有完全计算的值。但是,使用no wait中的Line 3,它如何工作?

假设Line 1触发4个线程,t1, t2, t3t4。假设N为8,则第一个for循环中的索引分区为:

t1: 0, 4
t2: 1, 5
t3: 2, 6
t4: 3, 7

假设t1首先完成索引04,然后降落到Line 6,现在到底发生了什么?如何保证它现在可以在相同的索引04上运行,而它们在上一次迭代中已正确计算出a的值?如果第二个for循环访问a[i+1]怎么办?

2 个答案:

答案 0 :(得分:7)

您引用的材料是错误的。如果在两个循环中都添加schedule(static),这将变得正确-这样可以保证连续循环的线程之间的索引分配相同。默认计划是由实现定义的,您不能假定它为static。引用标准:

  

时间表和迭代次数相同的不同循环区域,   即使它们出现在同一平行区域,也可以分布   线程之间的迭代方式有所不同。唯一的例外是   静态时间表,如表2.5所示。依赖的程序   哪个线程在其他任何线程下执行特定的迭代   情况不合格。

如果第二个for循环访问a[i+1],则必须将障碍完全留在那儿。

答案 1 :(得分:2)

对我来说,示例中没有潜在问题的说法是错误的。

实际上,调度将与未明确定义的调度相同。这将是默认值。此外,如果调度是a类型的,那么实际上不会有任何问题,因为在第二个循环内处理数组static中任何给定数据的线程将与第二个循环中的相同。一个会在第一个循环中编写的代码。

但是这里的实际问题是OpenMP标准没有定义默认调度。这是实现定义的...对于默认调度为dynamic的(很多)实现,代码段中不能有任何竞争条件。但是,如果默认调度为HTTP Error 404. The requested resource is not found. ,则您会注意到,会发生竞争情况,并且结果不确定。