Skip to content

Data Sharing Attribute

Shared variable

  • All the threads have access to the shared variable.
  • By default, in the parallel region, all the variables are considered shared variables except the loop iteration counter variables.

Note

Shared variables should be handled carefully; otherwise, they cause race conditions in the program.

Examples: Shared variable
#include <iostream>
#include <omp.h>

using namespace std;

int main()
{
  // Array size
  int N = 10;

  // Initialize the variables
  float *a;

  // Allocate the memory
  a  = (float*)malloc(sizeof(float) * N);

  //#pragma omp parallel for
  // or 
#pragma omp parallel for shared(a)
  for (int i = 0; i < N; i++)
    {
      a[i] = a[i] + i;  
      cout << "value of a in the parallel region" << a[i] << endl;
    }

  for (int i = 0; i < N; i++)
    cout << "value of a after the parallel region " << a[i] << endl;

  return 0;
}
program main
  use omp_lib
  implicit none

  ! Input vectors
  real(8), dimension(:), allocatable :: a

  integer :: n, i
  n=10

  ! Allocate memory for vector
  allocate(a(n))

  !$omp parallel shared(a)
  !$omp do
  do i = 1, n
      a(i) = a(i) + i
      print*, 'value of a in the parallel region', a(i)
  end do
  !$omp end do
  !$omp end parallel

  do i = 1, n
      a(i) = a(i) + i
      print*,'value of an after the parallel region', a(i)
  end do

  ! Delete the memory
  deallocate(a)

end program main
Questions
  • Does the value of vector a change after the parallel loop, if not why, think?
  • Do we really need to mention shared(a), is it neccessary?

Private variable

  • Each thread will have its own copy of the private variable.
  • And the private variable is only accessible within the parallel region, not outside of the parallel region.
  • By default, the loop iteration counters are considered as a private.
  • A change made by one thread is not visible to other threads.

Examples: Private variable
#include <iostream>
#include <omp.h>

using namespace std;

int main()
{
  // Array size
  int N = 10;

  // Initialize the variables
  float *a,b,c;
  b = 1.0;
  c = 2.0;

  // Allocate the memory
  a  = (float*)malloc(sizeof(float) * N);

#pragma omp parallel for private(b,c)
  for (int i = 0; i < N; i++)
    {
      b = a[i] + i;
      c = b + 10 * i;
      cout << "value of c in the parallel region " << c << endl;
    }

  cout << "value of c after the parallel region " << c << endl; 

  return 0;
}
program main
  use omp_lib
  implicit none

  ! Input vectors
  real(8), dimension(:), allocatable :: a

  real(8) :: b, c
  integer :: n, i  
  n=10
  b=1.0
  c=2.0

  ! Allocate memory for vector
  allocate(a(n))

  !$omp parallel private(b,c) shared(a)
  !$omp do
  do i = 1, n
      b = a(i) + i
      c = b + 10 * i
      print*, 'value of c in the parallel region', c
  end do
  !$omp end do
  !$omp end parallel
  print*, 'value of c after the parallel region', c

  ! Delete the memory
  deallocate(a)

end program main
Questions
  • What is the value of the variable c in the parallel region and after the parallel region?
  • After the parallel region, has variable c been updated or not?

Lastprivate

  • lastprivate: is also similar to a private clause
  • But each thread will have an uninitialized copy of the variables passed as lastprivate
  • At the end of the parallel loop or sections, the final variable value will be the last thread accessed value in the section or in a parallel loop.
Examples: Lastprivate variable
#include<iostream>
#include<omp.h>

using namespace std;

int main()
{
  int n = 10;
  int var = 5;
  omp_set_num_threads(10);
#pragma omp parallel for lastprivate(var)
  for(int i = 0; i < n; i++)
    {
      var += omp_get_thread_num();
      cout << " lastprivate in the parallel region " << var << endl;
    } /*-- End of parallel region --*/
  cout << "lastprivate after the parallel region " << var <<endl;

  return 0;
}
program main
  use omp_lib
  implicit none

  ! Initialise the variable
  real(8) :: var
  integer :: n, i  
  n = 10
  var = 5

  call omp_set_num_threads(10)

  !$omp parallel 
  !$omp do lastprivate(var)
  do i = 1, n
     var  =  var + omp_get_thread_num()
     print*, 'lastprivate in the parallel region ', var
  end do
  !$omp end do
  !$omp end parallel

  print*, 'lastprivate after the parallel region ', var

end program main
Questions
  • What is the value of the variable var in the parallel region and after the parallel region?
  • Do you think the initial value of variable var is considered within the parallel region?

Firstprivate

  • firstprivate: is similar to a private clause
  • But each thread will have an initialized copy of the variables passed as firstprivate
  • Available for parallel constructs, loops, sections and single constructs
Examples: Firstprivate variable
#include<iostream>
#include<omp.h>

using namespace std;

int main()
{
  int n = 10;
  int var = 5;
  omp_set_num_threads(10);
#pragma omp parallel for firstprivate(var)
  for(int i = 0; i < n; i++)
    {
      var += omp_get_thread_num();
      cout << " lastprivate in the parallel region " << var << endl;
    } /*-- End of parallel region --*/
  cout << "lastprivate after the parallel region " << var <<endl;

  return 0;
}
program main
  use omp_lib
  implicit none

  ! Initialise the variable
  real(8) :: var
  integer :: n, i  
  n = 10
  var = 5

  call omp_set_num_threads(10)

  !$omp parallel 
  !$omp do firstprivate(var)
  do i = 1, n
     var  =  var + omp_get_thread_num()
     print*, 'lastprivate in the parallel region ', var
  end do
  !$omp end do
  !$omp end parallel

  print*, 'lastprivate after the parallel region ', var

end program main
Questions
  • What is the value of the variable var in the parallel region and after the parallel region?
  • Is variable var has been updated after the parallel region, if not why, think?