5

在 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=yes --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)
4

1 回答 1

5

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

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

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

于 2013-09-20T14:29:53.940 回答