How can I make the parallel static and dynamic version of this two loops?

Viewed 90

I would like to know how to obtain the same result when I execute the parallel version of this code:

#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#define N 10000
int MAT[N][N], B[N], C[N];
void main ()
{
    int i, j, x = 0;
    for (i=0; i<N; i++) 
    {
        B[i] = i % 3;
        for (j=0; j<N; j++) MAT[i][j] = (i + j) % 7 - 2;
    }
    #pragma omp parallel for schedule(static,1)
    for (i=0; i<N; i++) {
        C[i] = 0;
        #pragma omp parallel for schedule(static,1)
        for (j=0; j<N; j++) 
            C[i] += MAT[i][j] * B[j];
        x += C[i];
    }
    printf ("\n x = %d\n", x);
}

The result must be 99990002 but I obtain different results with 2, 4, 8, 16 and 32 threads. And I must to obtain the same result with the static and dynamic parallel version with all that different number of threads.

1 Answers

The simples solution is to parallelize only the outer loop:

#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#define N 10000
int MAT[N][N], B[N];
void main ()
{
    int i, j, x = 0;
    for (i=0; i<N; i++){
        B[i] = i % 3;
        for (j=0; j<N; j++) 
            MAT[i][j] = (i + j) % 7 - 2;
    }
    #pragma omp parallel for schedule(static, 1) reduction(+:x)
    for (i=0; i<N; i++)
        for (j=0; j<N; j++) 
            x += MAT[i][j] * B[j];
    printf ("\n x = %d\n", x);
}

The dynamic version would be as follows:

 #pragma omp parallel for schedule(dynamic, 1) reduction(+:x)
  for (i=0; i<N; i++)
    for (j=0; j<N; j++) 
        x += MAT[i][j] * B[j];
  printf ("\n x = %d\n", x);

Apart from that, your code has the following issues:

#pragma omp parallel for schedule(static,1)
 for (i=0; i<N; i++) {
    C[i] = 0;
    #pragma omp parallel for schedule(static,1)

Your inner loop is not actually distributing the iterations among threads as you might have wanted. Because you added the parallel clause again, and assuming that you have nested parallelism disabled, which by default it is, each of the threads created in the outer parallel region will execute "sequentially" the code within that region, namely:

#pragma omp parallel for schedule(static,1)
for (j=0; j<N; j++) 
     C[i] += MAT[i][j] * B[j];
x += C[i];
}

The other problem is that you have a race condition during the update of the variable x, which can be solved by adding the OpenMP reduction clause into the parallel for (i.e., #pragma omp parallel for schedule(static, 1) reduction(+:x)). Lastly, since now we reduce the variable x, the array C is no longer anymore.

If you really want to parallelize both loops simultaneously, you need to use OpenMP collapse clause, and adapt your code accordingly, for instance:

#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#define N 10000
int MAT[N][N], B[N];
void main ()
{
    int i, j, x = 0;
    for (i=0; i<N; i++){
        B[i] = i % 3;
        for (j=0; j<N; j++)
            MAT[i][j] = (i + j) % 7 - 2;
    }

    #pragma omp parallel for schedule(static, 1) collapse(2) reduction(+:x)
    for (i=0; i<N; i++)
        for (j=0; j<N; j++)
            x += MAT[i][j] * B[j];
    printf ("\n x = %d\n", x);
}
Related