Helgrind (Valgrind) 和 OpenMP (C):避免误报?

Posted

技术标签:

【中文标题】Helgrind (Valgrind) 和 OpenMP (C):避免误报?【英文标题】:Helgrind (Valgrind) and OpenMP (C): avoiding false positives? 【发布时间】:2012-05-25 09:34:25 【问题描述】:

Valgrind 线程错误检测工具 Helgrind 的文档,找到 here

警告说,如果您使用 GCC 编译您的 OpenMP 代码,GCC 的 OpenMP 运行时库 (libgomp.so) 将导致数据争用的误报报告的混乱,因为它使用原子机器指令和 Linux futex 系统调用,而不是 POSIX pthreads 原语。它告诉您,您可以通过使用 --disable-linux-futex 配置选项重新编译 GCC 来解决此问题。

所以我尝试了这个。我使用 --disable-linux-futex 配置选项编译并安装到本地目录 (~/GCC_Valgrind/gcc_install) 新的 GCC 版本 4.7.0(撰写本文时的最新版本)。然后我创建了一个没有可见数据竞争的小型 OpenMP 测试程序 (test1.c):

/* test1.c */

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_THREADS 2

int a[NUM_THREADS];

int main(void) 
        int i;
#pragma omp parallel num_threads(NUM_THREADS)
        
                int tid = omp_get_thread_num();
                a[tid] = tid + 1;
        
        for (i = 0; i < NUM_THREADS; i++)
                printf("%d ", a[i]);
        printf("\n");
        return EXIT_SUCCESS;

我将这个程序编译如下

~/GCC_Valgrind/gcc_install/bin/gcc -Wall -fopenmp  -static -L~/GCC_Valgrind/gcc_install/lib64 -L~/GCC_Valgrind/gcc_install/lib -o test1 test1.c

但是,我收到了 30 份误报数据竞争报告!--全部发生在 libgomp 代码中。然后我编译了没有-static 标志的test1.c,然后再次运行Helgrind。这一次,我只收到了 9 个误报数据竞争报告,但这仍然太多了——而且,如果没有 -static 标志,我无法在 libgomp 代码中追踪假定的竞争。 p>

是否有人找到了一种方法来减少(如果不能消除)来自 Helgrind 的误报数据竞争报告的数量,该报告应用于使用 GCC 编译的 OpenMP 程序?谢谢!

【问题讨论】:

只是一个疯狂的猜测 - 可能是您重新编译的 gcc 链接到重新编译的 libgomp 版本,但动态链接器仍然加载提供的系统libgomp 在运行时?尝试使用-Wl,-rpath,/path/to/recompiled/lib 重新编译。 只是附注 - 在工具集仍然免费的情况下尝试使用 Oracle Solaris Studio for Linux 中的线程分析器工具 :) 您是否考虑过添加错误抑制? valgrind.org/docs/manual/manual-core.html#manual-core.suppress 只是为了确定,你能把tid标记为私人吗? @user1202136 你是怎么做到的? 【参考方案1】:

很抱歉把这个作为答案,因为它更像是一个评论,但它太长了,不适合作为评论,所以这里是:

来自您引用的网站。

GNU OpenMP(GCC 的一部分)的运行时支持库,至少对于 GCC 版本 4.2 和 4.3。 GNU OpenMP 运行时库 (libgomp.so) 使用以下组合构建自己的同步原语 原子内存指令和 futex 系统调用,这会导致总 Helgrind 的混乱,因为它无法“看到”那些。

幸运的是,这可以使用配置时选项来解决(对于 海湾合作委员会)。从源代码重建 GCC,并使用配置 --禁用-linux-futex。这使得 libgomp.so 改为使用标准的 POSIX 线程原语。请注意,这是使用 GCC 测试的 4.2.3 并且尚未使用更新的 GCC 版本重新测试。我们将不胜感激听到更多关于任何成功或失败的信息 最新版本。

正如您在帖子中提到的,这与 libgomp.so 有关,但这是一个共享对象,所以我看不出您如何传递 -static 标志并仍然使用该库。我是不是被误导了?

【讨论】:

【参考方案2】:

使其工作的步骤:

    使用--disable-linux-futex重新编译gcc(包括libgomp) 确保在编译程序时使用 futex free gcc。 确保系统在执行程序时会加载 futex free libgomp(该库通常位于GCC-OBJ-DIR/PLATFORM/libgomp/.libs)。例如通过设置LD_LIBRARY_PATH 环境变量:

导出 LD_LIBRARY_PATH=~/gcc-4.8.1-nofutex/x86_64-unknown-linux-gnu/libgomp/.libs:

【讨论】:

【参考方案3】:

还请注意,如果在代码中使用omp_set_lock,则必须替换omp.h 路径,因为锁结构大小不同。见https://xrunhprof.wordpress.com/2018/08/27/tsan-with-openmp/

【讨论】:

以上是关于Helgrind (Valgrind) 和 OpenMP (C):避免误报?的主要内容,如果未能解决你的问题,请参考以下文章

死锁问题分析的利器——valgrind的DRD和Helgrind

数据竞争(data race)问题分析的利器——valgrind的Helgrind

Valgrind

valgrind 内存调试工具

内存泄漏定位以及解决

PySide/Cython 和 GIL 多线程使用