只需编写一个小的OMP测试,并且它一直无法正常工作:

#include <omp.h>
int main() {
  int i,j=0;
#pragma omp parallel
  for(i=0;i<1000;i++)
  {
#pragma omp barrier
    j+= j^i;
  }
  return j;
}

用法 j 在此示例中,从所有线程编写都是不正确的,但是

  • j的不确定价值必须只有j

  • 我有冻结。

gcc-4.3.1 -fopenmp a.c -o gcc -static

在4核X86_Core2 Linux服务器上运行: $ ./gcc 并冻结(有时;像1冻结4-5个快速跑步)。

Strace:

[pid 13118] futex(0x80d3014, FUTEX_WAKE, 1) = 1
[pid 13119] <... futex resumed> )       = 0
[pid 13118] futex(0x80d3020, FUTEX_WAIT, 251, NULL <unfinished ...>
[pid 13119] futex(0x80d3014, FUTEX_WAKE, 1) = 0
[pid 13119] futex(0x80d3020, FUTEX_WAIT, 251, NULL                       
                        <freeze>

为什么我要冻结(僵局)?

有帮助吗?

解决方案

尝试使我私密,以便每个循环都有自己的副本。

现在我有更多的时间,我将尝试解释。默认情况下,OpenMP中的变量共享。在某些情况下,有一些默认值使变量私有。平行区域不是其中之一(因此高性能标记的响应是错误的)。在您的原始程序中,您有两个竞赛条件 - 一个在I上,一个在J上。问题在于i。每个线程将执行循环多次,但是由于我正在通过每个线程更改,因此任何线程执行循环的次数不确定。由于所有线程都必须执行要满足的障碍物的屏障,因此您提出了将挂在障碍物上的情况,而障碍物将永远不会结束,因为并非所有线程都会以相同的次数执行它。

由于OpenMP规格明确指出(OMP规格V3.0,第2.8.3节屏障结构),“团队中每个线程的工作共享区域和障碍区域的顺序必须相同”,您的程序是不合格的,并且因此,可能具有不确定的行为。

其他提示

您正在尝试从多个线程添加到同一位置。您无法同行尝试做的事情。如果您想并行进行总和,则需要将其分成较小的碎片并之后收集它们。

A5B的更新:正确的想法,但发现了错误的部分。这 i 两个线程都更改了变量。

@ejd,如果我将我标记为私人,我的程序会合规吗?

抱歉 - 我只是看到了这个问题。从技术上讲,如果您将变量“ i”标记为私有,那么您的程序将符合OpenMP。但是,“ J”仍然存在种族条件,尽管您的程序是合规性的(因为有有效的案例具有种族条件),但“ J”的值未指定(根据OpenMP规格)。

在您先前的答案之一中,您说您正在尝试衡量屏障实施的速度。您可能想查看一些已经为各种OpenMP构建体发布的结果的“基准”。一个是由马克·布尔(Mark Bull)(爱丁堡大学EPCC)撰写的,另一个是来自劳伦斯·利弗莫尔国家实验室(LLNL),第三个(Parkbench)来自日本的计算合作伙伴关系。他们可能会为您提供一些指导。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top