c - OpenMP,并行写入不同的数组元素

标签 c arrays thread-safety openmp valgrind

在 OpenMP 中,您可以并行写入该数组的不同元素吗?这是一个简单的测试程序:

#include <stdio.h>
#include <math.h>

int main(){

  const int n=100;
  int squares[n];

  // Can we write to distinct array elements simultaneously?
  // Valgrind+DRD doesn't like this.
#pragma omp parallel for
  for(int i=0; i<n; i++)
    squares[i]=i*i;

  // We definitely can read from distinct array elements simultaneously.
  int sumOfSquares=0;
#pragma omp parallel for reduction(+:sumOfSquares)
  for(int i=0; i<n; i++)
    sumOfSquares+=squares[i];

  // The result always seems to be correct.
  printf("sumOfSquares = %d = %d\n", sumOfSquares, n*(n-1)*(2*n-1)/6);

}

我用 gcc -std=c99 -fopenmp -g openmp_arrays.c 编译了上面的代码并用 valgrind --tool=drd --check-stack-var= 检查线程安全是的 --read-var-info=yes --dsymutil=yes a.out。该程序似乎总是给出正确的结果,但 Valgrind 给出了错误:

==18064== drd, a thread error detector
==18064== Copyright (C) 2006-2011, and GNU GPL'd, by Bart Van Assche.
==18064== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==18064== Command: a.out
==18064== 
==18064== Thread 2:
==18064== Conflicting load by thread 2 at 0x7ff000730 size 8
==18064==    at 0x4008B0: main._omp_fn.1 (openmp_arrays.c:16)
==18064==    by 0x4E45EE9: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4C2D9E1: ??? (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
==18064==    by 0x5053E99: start_thread (pthread_create.c:308)
==18064==    by 0x535CCCC: clone (clone.S:112)
==18064== Allocation context: unknown.
==18064== Other segment start (thread 1)
==18064==    at 0x4C2DF29: pthread_create@* (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
==18064==    by 0x4E4631B: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x40075E: main (openmp_arrays.c:10)
==18064== Other segment end (thread 1)
==18064==    at 0x4E47591: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4E466ED: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4007B1: main (openmp_arrays.c:16)
==18064== 
==18064== Conflicting load by thread 2 at 0x7ff000738 size 4
==18064==    at 0x4008BB: main._omp_fn.1 (openmp_arrays.c:16)
==18064==    by 0x4E45EE9: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4C2D9E1: ??? (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
==18064==    by 0x5053E99: start_thread (pthread_create.c:308)
==18064==    by 0x535CCCC: clone (clone.S:112)
==18064== Allocation context: unknown.
==18064== Other segment start (thread 1)
==18064==    at 0x4C2DF29: pthread_create@* (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
==18064==    by 0x4E4631B: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x40075E: main (openmp_arrays.c:10)
==18064== Other segment end (thread 1)
==18064==    at 0x4E47591: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4E466ED: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4007B1: main (openmp_arrays.c:16)
==18064== 
==18064== Conflicting load by thread 2 at 0x7ff00073c size 4
==18064==    at 0x40092B: main._omp_fn.1 (openmp_arrays.c:16)
==18064==    by 0x4E45EE9: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4C2D9E1: ??? (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
==18064==    by 0x5053E99: start_thread (pthread_create.c:308)
==18064==    by 0x535CCCC: clone (clone.S:112)
==18064== Allocation context: unknown.
==18064== Other segment start (thread 1)
==18064==    at 0x4C2DF29: pthread_create@* (in /usr/lib/valgrind/vgpreload_drd-amd64-linux.so)
==18064==    by 0x4E4631B: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x40075E: main (openmp_arrays.c:10)
==18064== Other segment end (thread 1)
==18064==    at 0x4E47591: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4E466ED: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==18064==    by 0x4007B1: main (openmp_arrays.c:16)
==18064== 
==18064== 
==18064== For counts of detected and suppressed errors, rerun with: -v
==18064== ERROR SUMMARY: 4 errors from 3 contexts (suppressed: 600066 from 59)

最佳答案

你绝对可以写不同的元素,你的例子是正确的。您可以查看 DRD 文档,它提供了更详细的示例

http://valgrind.org/docs/manual/drd-manual.html#drd-manual.openmp

顺便说一句,本文档指定“对于大多数 Linux 发行版 (...),您必须重新编译 GCC”才能使用 DRD,并提供专用脚本的路径。如果您跳过此步骤,这可能会解释您的问题。

关于c - OpenMP,并行写入不同的数组元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18918750/

相关文章:

ios - UIDocument 和 NSFileWrapper - NSFastEnumerationMutationHandler 在保存期间更改文件包装器时

c - printf 格式说明符的参数和 printf 格式说明符的额外参数中的类型无效

c - 在C中使用printf()和fork()复制输出

javascript - 在 Javascript 数组中添加相似的项目

Java - 将数组直接传递到构造函数中,而不是作为变量

c++ - 在 scoped_lock 上进行额外的解锁调用

C# - 连接事件期间出现 "Cross-thread operation not valid"错误

c - 在C中获取字符缓冲区中的值的数量(从文件读取)

c - 从链表的给定位置删除节点

javascript - javascript 中的 1 == [1] 是怎样的?