在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)

最佳答案

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

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

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

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

10-10 01:14