繁体   English   中英

关键部分的功能在OpenMP中产生数据竞争

[英]Functions in critical sections produce data races in OpenMP

对于在并行区域内使用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)

我理解警告,因为第7行和第13行上的数据争用是(* a)-和(* a)++调用。

我只是在阅读drd的文档 ,特别是第8.2.8节:

DRD支持GCC生成的OpenMP共享内存程序。 从4.2.0版开始,GCC支持OpenMP。 GCC对OpenMP程序的运行时支持由一个名为libgomp的库提供。 除非已使用--disable-linux-futex选项配置了库,否则在此库中实现的同步原语直接使用Linux的futex系统调用。 DRD仅支持使用此选项配置的libgomp库,并且其中存在符号信息。 对于大多数Linux发行版,这意味着您必须重新编译GCC。 另请参见Valgrind源代码树中的脚本drd / scripts / download-and-build-gcc,以获取有关如何编译GCC的示例。 您还必须确保在启动OpenMP程序时加载了新编译的libgomp.so库。

如果您不重新编译libgomp则可能是您遇到的奇怪行为的一种可能解释。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM