Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sections and OpenMP code hangs sometimes

Tags:

c++

c

openmp

I have this code using OpenMP and C++. The code executes correctly but sometimes it hangs. I am using sections. Can you tell me what is the problem? I tries several things but none of them worked, like changing the variables from private to shared.

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#define N     50

//gcc -fopenmp -o e3 e3.c
int main (int argc, char *argv[]) 
{
int i, nthreads, tid, section;
float a[N], b[N], c[N];
void print_results(float array[N], int tid, int section);

/* Some initializations */
for (i=0; i<N; i++)
  a[i] = b[i] = i * 1.0;

#pragma omp parallel private(c,i,tid,section)
  {
  tid = omp_get_thread_num(); //FIXME: how to get the thread id?
  if (tid == 0)
    {
    nthreads = omp_get_num_threads(); //FIXME: how to get the number of threads?
    printf("Number of threads = %d\n", nthreads);
    }

  /*** Use barriers for clean output ***/
  #pragma omp barrier
  printf("Thread %d starting...\n",tid);
  #pragma omp barrier

  #pragma omp sections nowait
    {
    #pragma omp section 
      {
      section = 1;
      for (i=0; i<N; i++)
        c[i] = a[i] * b[i];
      print_results(c, tid, section);
      }

    #pragma omp section
      {
      section = 2;
      for (i=0; i<N; i++)
        c[i] = a[i] + b[i];
      print_results(c, tid, section);
      }

    }  /* end of sections */

  /*** Use barrier for clean output ***/
  #pragma omp barrier
  printf("Thread %d exiting...\n",tid);

  }  /* end of parallel section */

printf("I am out of parallel scope\n");
return 0;
}



void print_results(float array[N], int tid, int section) 
{
  int i,j;

  j = 1;
  /*** use critical for clean output ***/
  #pragma omp critical
  {
  printf("\nThread %d did section %d. The results are:\n", tid, section);
  for (i=0; i<N; i++) {
    printf("%e  ",array[i]);
    j++;
    if (j == 6) {
      printf("\n");
      j = 1;
      }
    }
    printf("\n");
  } /*** end of critical ***/

  #pragma omp barrier
  printf("Thread %d done and synchronized.\n", tid); 

}

Thank you!

like image 945
O.Shaya Avatar asked Mar 15 '23 20:03

O.Shaya


2 Answers

Barriers are used to synchronize all threads. All threads will be blocked until all threads have reached the barrier. As a consequence of this, in order for your program to terminate, all threads have to reach the same number of barriers during their life. If one thread has more barriers than the others, that thread can never pass its extra barrier because it will wait for the other threads - which will never get there because they don't have that extra barrier.

You have a barrier in the function print_results, which is only executed by the threads that happen to be assigned one of the two sections. All extra threads have one barrier less. That unequal number of barriers blocks your program.

Make sure to place barriers only in places where you know that all threads will execute it.

like image 128
mastov Avatar answered Mar 23 '23 15:03

mastov


I am not really sure yet what is happening, though I found a "work-around".

You only use two sections, but allow more than two threads. If you restrict the number of threads to two by changing

#pragma omp parallel private(c,i,tid,section)

to

#pragma omp parallel private(c,i,tid,section) num_threads(2),

the program will terminate. (I was unable to reproduce the error.)

If you set the number of threads to three, the program will always hang. (At least it never terminated. I tried about 20 times.)

like image 26
MisterC Avatar answered Mar 23 '23 15:03

MisterC