In OpenMP can you write to distinct elements of that array in parallel? Here's a simple test program:
#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);
}
I compiled the above code with gcc -std=c99 -fopenmp -g openmp_arrays.c
and checked thread safety with valgrind --tool=drd --check-stack-var=yes --read-var-info=yes --dsymutil=yes a.out
. The program always seems to give correct results, but Valgrind gives errors:
==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)
You definitely can write to distinct elements, and your example is correct. You can have a look at the DRD documentation which provides a more elaborate example
http://valgrind.org/docs/manual/drd-manual.html#drd-manual.openmp
Btw, this documentation specifies that "for most Linux distributions (...) you will have to recompile GCC" to use DRD and provides the path to the dedicated script. This might explain your problem in case you skipped this step.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With