Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenMP, writing to distinct array elements in parallel

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)
like image 661
Douglas B. Staple Avatar asked Sep 20 '13 14:09

Douglas B. Staple


1 Answers

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.

like image 93
P-Gn Avatar answered Nov 13 '22 09:11

P-Gn