【问题标题】:Can I use Thread Sanitizer for OpenMP programs?我可以将 Thread Sanitizer 用于 OpenMP 程序吗?
【发布时间】:2016-01-05 10:15:34
【问题描述】:

考虑以下示例:

#include <iostream> 

int main () {
    int i = 0;
    #pragma omp parallel
    {
        #pragma omp critical
        {
            ++i;
        }
    }
    std::cout << i;
}

g++ -fopenmp -fsanitize=thread编译并运行yield

警告:ThreadSanitizer:数据竞争 (pid=9576)
线程 T1 在 0x7ffdc170f600 读取大小 4:
#0 main._omp_fn.0 (a.out+0x000000400d20)
#1 gomp_thread_start /build/gcc/src/gcc-5.2.0/libgomp/team.c:118 (libgomp.so.1+0x00000000f42d)

线程 T2 先前在 0x7ffdc170f600 写入大小 4:
#0 main._omp_fn.0 (a.out+0x000000400d35)
#1 gomp_thread_start /build/gcc/src/gcc-5.2.0/libgomp/team.c:118 (libgomp.so.1+0x00000000f42d)

位置是主线程的堆栈。

主线程在以下位置创建的线程 T1 (tid=9578, running):
#0 pthread_create /build/gcc/src/gcc-5.2.0/libsanitizer/tsan/tsan_interceptors.cc:895 (libtsan.so.0+0x000000027a37)
#1 gomp_team_start /build/gcc/src/gcc-5.2.0/libgomp/team.c:796 (libgomp.so.1+0x00000000f98f)
#2 __libc_start_main (libc.so.6+0x00000002060f)

主线程在以下位置创建的线程 T2 (tid=9579, running):
#0 pthread_create /build/gcc/src/gcc-5.2.0/libsanitizer/tsan/tsan_interceptors.cc:895 (libtsan.so.0+0x000000027a37)
#1 gomp_team_start /build/gcc/src/gcc-5.2.0/libgomp/team.c:796 (libgomp.so.1+0x00000000f98f)
#2 __libc_start_main (libc.so.6+0x00000002060f)

摘要:ThreadSanitizer:数据竞争 ??:0 main._omp_fn.0

据我所知,这是误报。有没有办法避免这种情况?

(使用 clang 和 libomp 也可以。)

【问题讨论】:

  • 如果要分析代码,还需要使用 TSAN 构建 OpenMP 运行时库;否则添加抑制?
  • @KerrekSB 我担心这是唯一的答案。在我的 Ubuntu 12.04 工作机器上构建现代东西并让它工作并不是很有趣。
  • @KerrekSB 你能详细说明压制的东西吗?我需要为每一个错误命中都这样做吗?在我们的生产代码中,有很多,如果我必须“手动”检查所有这些,那么消毒剂就会失去意义。
  • 我认为您应该能够通过代码位置进行压制。我从来没有这样做过(我写的最后一个抑制集是为 Valgrind 编写的),但请查看 wiki:github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions

标签: c++ c gcc thread-sanitizer


【解决方案1】:

即使使用抑制,您仍然会在 OpenMP 运行时得到误报,因为运行时中有一些 Tsan 无法理解的同步机制。

我们致力于 OpenMP 运行时,以使 Tsan 了解此同步点并消除所有误报。

看看这个项目:

https://github.com/PRUNER/archer

如果您需要更多帮助,请告诉我。

最好的,

西蒙娜

【讨论】:

  • 谢谢,有机会我会去看看。不过可能有点,我现在正在做其他事情,一位同事负责消毒剂的工作。
【解决方案2】:

是的,至少对于 Clang,这相对容易。您需要使用 ThreadSanitizer 支持构建 libomp(Clang 使用它而不是 libgomp)。这不会花那么长时间:

git clone https://github.com/llvm/llvm-project
cd llvm-project
mkdir build
cd build
cmake -DLIBOMP_TSAN_SUPPORT=1 ../openmp
sudo cmake --build . --target install

sudo--target install 是可选的,如果您将路径调整为下面的libomp.so

如果您使用此 libomp.so 而不是系统之一,现在运行您的示例不会出现任何错误:

clang++ -fsanitize=thread -fopenmp main.cpp
env LD_PRELOAD=/usr/local/lib/libomp.so ./a.out

【讨论】:

  • 显然这适用于具有 64 位 Intel CPU 的 Linux。 CMake 脚本检查if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" AND ${INTEL64})
  • INTEL64 将为 AMD CPU(或其他 x86_64 CPU)设置。查看llvm-project的根CMakeLists.txt
  • 当然。但对我来说,重要的是启动 Linux,不幸的是,这在 macOS 上不起作用。我认为这是添加到答案中的相关信息。一旦我在 Linux 上,这非常有效!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
  • 2021-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多