6

I've just started to program with openmp and I'm trying to parallelize a for loop with a variable that I need out of the loop. Something like this:

float a = 0;
for (int i = 0; i < x; i++)
{
    int x = algorithm();
    /* Each loop, x have a different value*/
    a = a + x;
}
cout << a;

I think the variable a has to be a local variable for each thread. After those thread have ended their job, all the local variables a should be added into one final result.

How can I do that?

2
  • Sorry for my english, I'm from Spain and I'm still learning :) Commented Nov 7, 2018 at 10:01
  • As long as they are declared inside the loop, they should be private by default. Commented Nov 7, 2018 at 10:06

3 Answers 3

5

There are many mechanisms how to achieve your goal, but the most simple is to employ OpenMP parallel reduction:

float a = 0.0f;
#pragma omp parallel for reduction(+:a)
for(int i = 0; i < x; i++) 
  a += algorithm();
cout << a;
Sign up to request clarification or add additional context in comments.

3 Comments

OMG Thank you so much! And what happen if instead of 'a' being a float is an array? I mean, for example, if each time you do a loop, it modifies one position of the array, depending the position on the algorithm (in this case you can modify lots of time the same position)
Yes, it's possible since OpenMP 4.5. There have been many questions about this topic asked, see, e.g. Reducing on array in OpenMP.
@EndergirlPG BTW in case of very large arrays, creating a thread-local temporary array for each thread might not be possible. Then, you basically need to update the shared array (e.g., by using atomic updates). However, you should use some really clever (cache-blocked) access to this output array, mainly to prevent false sharing. Otherwise, the performance would be very low.
5

Use the #pragma omp parallel for reduction(+:a) clause before the for loop

variable declared within the for loop are local, as well as loop counters variable declared outside the #pragma omp parallel block are shared by default, unless otherwise specified (see shared, private, firstprivate clauses). Care should be taken when updating shared variables as a race condition may occur. In this case, the reduction(+:a) clause indicated that a is a shared variable on which an addition is performed at each loop. Threads will automatically keep track of the total amount to be added and safely increment a at the end of the loop.

Both codes below are equivalent:

float a = 0.0f;
int n=1000;
#pragma omp parallel shared(a) //spawn the threads
{
float acc=0;        // local accumulator to each thread
#pragma omp for     // iterations will be shared among the threads
for (int i = 0; i < n; i++){
      float x = algorithm(i); //do something
      acc += x;     //local accumulator increment
  } //for
#omp pragma atomic
a+=acc; //atomic global accumulator increment: done on thread at a time
} //end parallel region, back to a single thread
cout << a;

Is equivalent to:

float a = 0.0f;
int n=1000;
#pragma omp parallel for reduction(+:a)
for (int i = 0; i < n; i++){
    int x = algorithm(i);
    a += x;
    } //parallel for
cout << a;

Note that you can't make a for loop with a stop condition i<x where x is a local variable defined within the loop.

Comments

1

You can use the following structure to perform parallel reduction with thread-private containers since your update is scalar associative.

float a = 0;//Global and will be shared.
#pragma omp parallel 
{
    float y = 0;//Private to each thread
#pragma omp for
    for(int i = 0; i < x; i++)
         y += algorithm();//Better practice is to not use same variable as loop termination variable.
//Still inside parallel
#pragma omp atomic
    a += y;
 }
cout << a;

2 Comments

That's exactly what OpenMP reduction is for. BTW x inside the OP's loop is not the termination variable, its a new local variable.
Agreed on the x part and modified my answer accordingly. I think for a beginner, breaking this down into smaller parts makes for better understanding of what is going on instead of using all clauses in one go.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.