误报“DRD的负载冲突”?

时间:2013-12-06 13:40:57

标签: c++ openmp valgrind race-condition

使用DRD(valgrind)分析我的C ++代码会发现“冲突加载”,但我看不出原因。代码如下:

int* x;
int Nt = 2;

x = new int[Nt];

omp_set_num_threads(Nt);

#pragma omp parallel for
for (int i = 0; i < Nt; i++)
{
    x[i] = i;
}

for (int i = 0; i < Nt; i++)
{
    printf("%d\n", x[i]);
}

程序运行良好,但是当主线程打印出x [1]的值时,DRD会发现问题。除了由于x阵列的分配方式而可能存在错误共享之外,我不明白为什么会出现任何冲突,以及如何避免这种冲突...请问有什么见解吗?

编辑以下是上述代码的DRD输出(第47行对应于printf语句):

==2369== Conflicting load by thread 1 at 0x06031034 size 4
==2369==    at 0x4008AB: main (test.c:47)
==2369== Address 0x6031034 is at offset 4 from 0x6031030. Allocation context:
==2369==    at 0x4C2DCC7: operator new[](unsigned long) (vg_replace_malloc.c:363)
==2369==    by 0x400843: main (test.c:37)
==2369== Other segment start (thread 2)
==2369==    at 0x4C31EB8: pthread_mutex_unlock (drd_pthread_intercepts.c:703)
==2369==    by 0x4C2F00E: vgDrd_thread_wrapper (drd_pthread_intercepts.c:236)
==2369==    by 0x5868D95: start_thread (in /lib64/libpthread-2.15.so)
==2369==    by 0x5B6950C: clone (in /lib64/libc-2.15.so)
==2369== Other segment end (thread 2)
==2369==    at 0x5446846: ??? (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.7.3/libgomp.so.1.0.0)
==2369==    by 0x54450DD: ??? (in /usr/lib64/gcc/x86_64-pc-linux-gnu/4.7.3/libgomp.so.1.0.0)
==2369==    by 0x4C2F014: vgDrd_thread_wrapper (drd_pthread_intercepts.c:355)
==2369==    by 0x5868D95: start_thread (in /lib64/libpthread-2.15.so)
==2369==    by 0x5B6950C: clone (in /lib64/libc-2.15.so)

1 个答案:

答案 0 :(得分:1)

GNU OpenMP运行时(libgomp)使用线程池实现OpenMP线程团队。创建它们之后,线程停靠在屏障上,等待它们被唤醒以执行特定任务。在GCC中,这些任务以轮廓(与内联相反)代码段的形式出现,即并行区域(或显式OpenMP任务)的代码被提取到单独的函数中,并提供给某些等待的线程作为执行任务。然后提升对接屏障并且线程开始执行任务。一旦完成,线程再次停靠 - 它们没有连接,而只是暂停。因此,从DRD的角度来看,在并行区域之后执行代码的串行部分的主线程正在访问,而没有可能由其他线程写入的保护资源。这当然不可能发生,因为其他线程停靠并等待新任务。

这种误报在DRD等通用工具中很常见,因为它们不了解OpenMP的特定语义。因此,这些工具不适合分析OpenMP程序。您应该使用专门的工具,例如Sun / Oracle Solaris Studio for Linux或商用Intel Inspector提供的免费线程分析器。后者可以免费使用,具有非商业开发目的的许可。这两个工具都了解OpenMP的细节,并且不会将这种情况作为可能的数据竞争对象。