Search code examples
cmultithreadingperformanceparallel-processingopenmp

Functions dependency openMP


I have 5 functions A,B,C,D,E.

To execute D I need B, C to be executed, to execute E I need A, D to be executed.

I have tried this

int main()
{
    #pragma omp parallel num_threads(5) 
    {
        long t1 = clock();
        int a = 0, b = 0, c = 0, d = 0, e = 0;
        int th = omp_get_thread_num();
        if (th == 0) {
            a += A();
            printf("A is finished after %d\n", clock() - t1);
        }
        if (th == 1) {
            b += B();
            printf("B is finished after %d\n", clock() - t1);
        }
        if (th == 2) {
            c += C();
            printf("C is finished after %d\n", clock() - t1);
        }
        if (th == 3 && (b == 1 && c == 1)) {
            d += D();
            printf("D is finished after %d\n", clock() - t1);
        }
        if (th == 4 && (a == 1 && d == 1)) {
            e += E();
            printf("E is finished after %d\n", clock() - t1);
        }

    }
    return 0;
}

but D, E haven't execute

All of these functions return 1 till now for debugging purpose


Solution

  • The variables a, b, c and d, cannot be used to communicate among threads because they are all private. Hence, each thread has its own private copy of them. Moreover, it is normally not a good idea to use them for synchronization purposes.

    In your code thread=3 would never wait on if (th == 3 && (b == 1 && c == 1)) because:

    1. b and c are private, so thread=3 has b=0 and c=0 regardless of what the other threads have done to their copies of the variables b=0 and c=0.
    2. There is nothing telling that thread to wait (e.g., some synchronization-alike constructor).

    If you want threads to wait for each other use the omp barrier instead. All threads will have to call the barrier before they can proceed with their computation.

     int main()
        {
            #pragma omp parallel num_threads(5) 
            {
                long t1 = clock();
                int a = 0, b = 0, c = 0, d = 0, e = 0;
                int th = omp_get_thread_num();
                if (th == 0) {
                    a += A();
                    printf("A is finished after %d\n", clock() - t1);
                }
                if (th == 1) {
                    b += B();
                    printf("B is finished after %d\n", clock() - t1);
                }
                if (th == 2) {
                    c += C();
                    printf("C is finished after %d\n", clock() - t1);
                }
                // Threads will wait for each other here
                #pragma omp barrier 
                if (th == 3) {
                    d += D();
                    printf("D is finished after %d\n", clock() - t1);
                }
                // Threads will wait for each other here
                #pragma omp barrier 
                if (th == 4) {
                    e += E();
                    printf("E is finished after %d\n", clock() - t1);
                }
            }
            return 0;
        }
    

    A more sophisticated approach would be to use tasks with dependencies a feature released on the OpenMP 4.0 standard. There is already a nice explanation about how this feature works on this thread.

    int a = 0, b = 0, c = 0, d = 0, e = 0;
    #pragma omp parallel num_threads(5) shared(a, b, c, d)
    {
      #pragma omp single nowait
      {
          long t1 = clock();
    
          int th = omp_get_thread_num();
          #pragma omp task  depend (out:a) 
          {
              a += A();
              printf("A is finished after %d\n", clock() - t1);
          }
          #pragma omp task depend (out:b) 
          {
             b += B();
             printf("B is finished after %d\n", clock() - t1);
          }
          #pragma omp task depend (out:c) 
          { 
              c += C();
              printf("C is finished after %d\n", clock() - t1);
          }
         #pragma omp task depend (in:a, b) depend(out:d) 
         {
            d += D(); 
            printf("D is finished after %d\n", clock() - t1);
         }
         #pragma omp task depend (in:a, b)  
         {
           e += E();
           printf("E is finished after %d\n", clock() - t1);
         }
      }
    }
    return 0;
    }