考虑以下示例:
#include <iostream>
int main () {
int i = 0;
#pragma omp parallel
{
#pragma omp critical
{
++i;
}
}
std::cout << i;
}
使用g++ -fopenmp -fsanitize=thread
进行编译并运行产量
警告:ThreadSanitizer:数据竞争(pid = 9576)
通过线程T1读取大小4在0x7ffdc170f600:
#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,正在运行):
#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,正在运行):
#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的东西也可以。)
答案 0 :(得分:4)
即使有了抑制,你仍然会在OpenMP运行时得到误报,因为在运行时内有一些Tsan无法理解的同步机制。
我们在OpenMP运行时工作,让Tsan了解这个同步点并删除所有误报。
看看这个项目:
https://github.com/PRUNER/archer
如果您需要更多帮助,请与我联系。
最佳,
西蒙
答案 1 :(得分:4)
是的,至少对于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