关于在并行区域内使用 critical,我似乎严重缺乏对 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 天时间试图找出错误,但我没有 找到它。如果有人能给我提示到底是什么,那就太好了 我不明白。
感谢任何帮助。
编辑: 我的 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)
我将警告理解为 a 上的数据竞争,第 7 行和第 13 行是 (*a)-- 和 (*a)++ 调用。
最佳答案
我刚刚正在阅读 documentation drd,特别是第 8.2.8 节:
DRD supports OpenMP shared-memory programs generated by GCC. GCC supports OpenMP since version 4.2.0. GCC's runtime support for OpenMP programs is provided by a library called libgomp. The synchronization primitives implemented in this library use Linux' futex system call directly, unless the library has been configured with the --disable-linux-futex option. DRD only supports libgomp libraries that have been configured with this option and in which symbol information is present. For most Linux distributions this means that you will have to recompile GCC. See also the script drd/scripts/download-and-build-gcc in the Valgrind source tree for an example of how to compile GCC. You will also have to make sure that the newly compiled libgomp.so library is loaded when OpenMP programs are started.
如果您没有重新编译 libgomp
,这可能是您遇到的奇怪行为的可能解释。
关于c - 关键部分中的函数在 OpenMP 中产生数据竞争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12635045/