1

只需编写一个小 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 必须只有非确定性值

  • 我有一个冻结。

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

在 4 核 x86_Core2 Linux 服务器上运行:$ ./gcc并被冻结(有时;例如 1 冻结 4-5 次快速运行)。

追踪:

[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>

为什么我会出现冻结(死锁)?

4

3 回答 3

4

尝试将 i 设为私有,以便每个循环都有自己的副本。

现在我有更多的时间,我会试着解释一下。默认情况下,OpenMP 中的变量是共享的。在某些情况下,存在使变量私有的默认值。并行区域不是其中之一(因此高性能标记的响应是错误的)。在您的原始程序中,您有两个竞争条件 - 一个在 i 上,一个在 j 上。问题在于 i 上的那个。每个线程都会执行循环若干次,但由于每个线程都在更改 i,因此任何线程执行循环的次数是不确定的。由于所有线程都必须执行屏障才能满足屏障,因此您会遇到这样的情况,即您将在永远不会结束的屏障上挂起,因为并非所有线程都会执行相同的次数。

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

于 2010-12-22T18:50:43.170 回答
1

您正在尝试从多个线程添加到同一位置。你不能同时做你想做的事情。如果要并行求和,则需要将其分成较小的部分,然后再收集。

a5b 更新:发现了正确的想法,但发现了错误的代码部分。i变量由两个线程更改。

于 2010-12-20T23:18:28.827 回答
0

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

对不起 - 我刚看到这个问题。从技术上讲,如果您将变量“i”标记为私有,您的程序将与 OpenMP 兼容。但是,“j”仍然存在竞争条件,并且当您的程序符合要求时(因为存在具有竞争条件的有效案例),“j”的值未指定(根据 OpenMP 规范)。

In one of your previous answers you said that you were trying to measure the speed of the barrier implementation. There are several "benchmarks" that you might want to look at that have published results for a variety of OpenMP constructs. One was written by Mark Bull (EPCC, University of Edinburgh), another (Sphinx) comes from Lawrence Livermore National Labs (LLNL), and the third (Parkbench) comes from a Japanese Computing Partnership. They may offer you some guidance.

于 2011-01-19T15:54:57.103 回答