paradiso
paradiso

Reputation: 379

Communicating between OpenMP threads

I have an OpenMP loop where I want the first iteration to complete before any of the other threads continue. I've tried using a global variable, initialized to 'false', which is set to 'true' when the first iteration finishes, but this doesn't appear to work as expected (I get stuck in an infinite loop).

For example:

    bool FirstDone = false; // This is a global variable
    ...
    #pragma omp parallel for
    for(int i=0;i<max;i++)
    {
        while(!FirstDone && i>0){}

        if(i==0)
        {
            // Do something
            FirstDone = true;
        }
    }

Can anyone shed light on why this isn't working?

Upvotes: 0

Views: 1875

Answers (6)

Massimiliano
Massimiliano

Reputation: 8032

I'll try here to rephrase the answer of @HighPerformanceMark in a more explicit manner (i.e. with some code sketches to support statements). Just to fix ideas, let's say that a serial version of your loop looks like:

for(int ii = 0; ii < max; ii++)
{   
    // Do a lot of work based on ii
    if(ii==0)
    {
        //////////////////////////////////////////////////
        // Do something special for the first iteration //
        //////////////////////////////////////////////////
    }
}

What was briefly proposed in a previous answer was to parallelize it with this simple logic

// Move the loop body into a function
void loopIteration(const size_t ii) {
    // Do a lot of work based on ii
}

#pragma omp parallel
{
// Single directive: the first one enters, the other wait at the implicit barrier
#pragma omp single
    {
        loopIteration(0);
        //////////////////////////////////////////////////
        // Do something special for the first iteration //
        //////////////////////////////////////////////////
    } // single: implicit barrier
// Loop work-sharing construct on the remaining iterations
#pragma omp for
    for(int ii = 1; ii < max; ii++)
    {   
       loopIteration(ii);         
    } // for: implicit barrier
} // parallel

The main ideas are to move the loop body into a function to avoid code duplication and to unroll explicitly the first iteration from the loop.

Upvotes: 2

damienfrancois
damienfrancois

Reputation: 59072

Have you tried simply removing the.empty while loop and setting a barrier after the if statement ?

Upvotes: 0

Hasturkun
Hasturkun

Reputation: 36402

I think you can achieve this by using an ordered clause and region, eg.

#pragma omp parallel for ordered
for(int i=0;i<max;i++)
{
    #pragma omp ordered
    if (i == 0)
    {
        // Do stuff in the first iteration, others wait.
    }

}

This may incur a performance overhead.

Upvotes: 1

High Performance Mark
High Performance Mark

Reputation: 78316

You could wrap the first iteration inside an OpenMP single construct. This will ensure that the first thread to encounter the construct will execute it and that all the other threads will wait until it is finished before continuing with the rest of the computation.

Upvotes: 2

MelMed
MelMed

Reputation: 1752

Use this one

 #pragma omp parallel for

it starts by default with your first iteration.

Upvotes: 1

Iłya Bursov
Iłya Bursov

Reputation: 24146

do first iteration outside the loop, start for with i=1, if you want to proceed with your logic, change FirstDone to volatile, but it still will not work, as there is no guarantee of thread ordering

Upvotes: 2

Related Questions