我似乎严重缺乏对OpenMP在并行区域内使用关键字的理解。我的问题很简单:为什么下面的代码 用valgrind drd制作警告?
#include <stdio.h>
#include <unistd.h>
void A(int* a)
{
printf("a++\n");
(*a)++;
}
void B(int* a)
{
printf("a--\n");
(*a)--;
}
void f(int* a)
{
#pragma omp critical
A(a);
sleep(1); /* work done here */
#pragma omp critical
B(a);
}
int main(int argc, char** argv)
{
int i;
int a = 0;
#pragma omp parallel for
for(i = 0; i < 4; ++i)
{
f(&a);
}
return 0;
}
用以下代码编译:
gcc -fopenmp -g -o omptest omptest.c
valgrind电话是
valgrind --tool=drd --check-stack-var=yes ./omptest
我的理解是关键部分应该保护我完全不受影响 警告我得到了。我现在花了两天时间试图找出错误,但事实并非如此 找到它。如果有人能给我一个确切的提示,那将是非常好的 我不明白。
感谢任何帮助。
修改 我的2 CPU机器上的(重复)警告是:
Thread 2:
Conflicting load by thread 2 at 0x7fefffecc size 4
at 0x4007DE: A (omptest.c:7)
by 0x40082E: f (omptest.c:19)
by 0x400902: main._omp_fn.0 (omptest.c:35)
by 0x4E45EE9: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
by 0x4C2D9E1: ??? (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
by 0x5053E99: start_thread (pthread_create.c:308)
by 0x535B39C: clone (clone.S:112)
Allocation context: unknown.
Other segment start (thread 1)
at 0x4C2DF29: pthread_create@* (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
by 0x4E4631B: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
by 0x400889: main (omptest.c:32)
Other segment end (thread 1)
at 0x5326F1D: ??? (syscall-template.S:82)
by 0x5326DBB: sleep (sleep.c:138)
by 0x40083D: f (omptest.c:21)
by 0x400902: main._omp_fn.0 (omptest.c:35)
by 0x400895: main (omptest.c:32)
Conflicting store by thread 2 at 0x7fefffecc size 4
at 0x4007E7: A (omptest.c:7)
by 0x40082E: f (omptest.c:19)
by 0x400902: main._omp_fn.0 (omptest.c:35)
by 0x4E45EE9: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
by 0x4C2D9E1: ??? (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
by 0x5053E99: start_thread (pthread_create.c:308)
by 0x535B39C: clone (clone.S:112)
Allocation context: unknown.
Other segment start (thread 1)
at 0x4C2DF29: pthread_create@* (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
by 0x4E4631B: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
by 0x400889: main (omptest.c:32)
Other segment end (thread 1)
at 0x5326F1D: ??? (syscall-template.S:82)
by 0x5326DBB: sleep (sleep.c:138)
by 0x40083D: f (omptest.c:21)
by 0x400902: main._omp_fn.0 (omptest.c:35)
by 0x400895: main (omptest.c:32)
Thread 1:
Conflicting load by thread 1 at 0x7fefffecc size 4
at 0x400805: B (omptest.c:13)
by 0x40084E: f (omptest.c:24)
by 0x400902: main._omp_fn.0 (omptest.c:35)
by 0x400895: main (omptest.c:32)
Allocation context: unknown.
Other segment start (thread 2)
at 0x535B361: clone (clone.S:84)
Other segment end (thread 2)
at 0x5326F1D: ??? (syscall-template.S:82)
by 0x5326DBB: sleep (sleep.c:138)
by 0x40083D: f (omptest.c:21)
by 0x400902: main._omp_fn.0 (omptest.c:35)
by 0x4E45EE9: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
by 0x4C2D9E1: ??? (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
by 0x5053E99: start_thread (pthread_create.c:308)
by 0x535B39C: clone (clone.S:112)
Conflicting store by thread 1 at 0x7fefffecc size 4
at 0x40080E: B (omptest.c:13)
by 0x40084E: f (omptest.c:24)
by 0x400902: main._omp_fn.0 (omptest.c:35)
by 0x400895: main (omptest.c:32)
Allocation context: unknown.
Other segment start (thread 2)
at 0x535B361: clone (clone.S:84)
Other segment end (thread 2)
at 0x5326F1D: ??? (syscall-template.S:82)
by 0x5326DBB: sleep (sleep.c:138)
by 0x40083D: f (omptest.c:21)
by 0x400902: main._omp_fn.0 (omptest.c:35)
by 0x4E45EE9: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
by 0x4C2D9E1: ??? (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
by 0x5053E99: start_thread (pthread_create.c:308)
by 0x535B39C: clone (clone.S:112)
我理解第7行和第13行的数据竞争警告是(* a) - 和(* a)++调用。
答案 0 :(得分:1)
我刚刚阅读了drd的documentation,特别是第8.2.8节:
DRD支持GCC生成的OpenMP共享内存程序。 GCC 从版本4.2.0开始支持OpenMP。 GCC对OpenMP的运行时支持 程序由名为libgomp的库提供。同步 在这个库中实现的原语使用Linux的futex系统调用 直接,除非库配置了 --disable-linux-futex选项。 DRD仅支持已使用此选项配置的libgomp库以及符号信息 存在。对于大多数Linux发行版而言,这意味着您将拥有 重新编译GCC。另请参见脚本 在Valgrind源代码树中使用drd / scripts / download-and-build-gcc 如何编译GCC的示例。你还必须确保这一点 在OpenMP程序中加载新编译的libgomp.so库 开始了。
如果您没有重新编译libgomp
,这可能是您遇到的奇怪行为的可能解释。